在协商时删除重复的XSLT

时间:2013-06-12 08:16:59

标签: xslt

我的XML如下所示:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<BATCHES>
    <item>
        <Material>1000000079</Material>
        <Description>330 Bulk</Description>
        <Tank>T123</Tank>
        <Batch>2013225287</Batch>
    </item>
    <item>
        <Material>1000000079</Material>
        <Description>330 Bulk</Description>
        <Tank>T123</Tank>
        <Batch>2013225301</Batch>
    </item>
    <item>
        <Material>1000000196</Material>
        <Description>340R Bulk</Description>
        <Tank>T700</Tank>
        <Batch>1000188378</Batch>
    </item>
    <item>
        <Material>1000002754</Material>
        <Description>43 Bulk</Description>
        <Tank>T515</Tank>
        <Batch>2013180125</Batch>
    </item>
    <item>
        <Material>1000002754</Material>
        <Description>43 Bulk</Description>
        <Tank>T515</Tank>
        <Batch>2013203124</Batch>
    </item>
    <item>
        <Material>1000002754</Material>
        <Description>43 Bulk</Description>
        <Tank>T515</Tank>
        <Batch>2013214839</Batch>
    </item>
    <item>
        <Material>1000002754</Material>
        <Description>OGA 72043 Bulk</Description>
        <Tank>T517</Tank>
        <Batch>2013214342</Batch>
    </item>
</BATCHES>

我的XSLT看起来像是:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output encoding="UTF-8" indent="yes" method="xml" version="1.0"/>
    <xsl:template match="/">
        <Rowsets>
            <Rowset>
                <xsl:variable name="materials" select=".//item[Tank!='RECV' and Tank!='PARK'] "/>
                <xsl:for-each select="$materials">
                    <xsl:if test="generate-id(.)=                       generate-id($materials[Material=current()/Material])">
                        <Row>
                            <Material>
                                <xsl:value-of select="Material"/>
                            </Material>
                            <Description>
                                <xsl:value-of select="Description"/>
                            </Description>
                            <Value>
                                <xsl:for-each select="$materials[Material=current()/Material]/Tank">
                                    <xsl:if test="node()">
                                        <xsl:value-of select="concat(.,'||')"/>
                                    </xsl:if>
                                </xsl:for-each>
                            </Value>
                        </Row>
                    </xsl:if>
                </xsl:for-each>
            </Rowset>
        </Rowsets>
    </xsl:template>
</xsl:stylesheet>

XSLT的结果是:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Rowsets>
    <Rowset>
        <Row>
            <Material>1000000079</Material>
            <Description>330 Bulk</Description>
            <Value>T123||T123||</Value>
        </Row>
        <Row>
            <Material>1000000196</Material>
            <Description>340R Bulk</Description>
            <Value>T700||</Value>
        </Row>
        <Row>
            <Material>1000002754</Material>
            <Description>43 Bulk</Description>
            <Value>T515||T515||T515||T517||</Value>
        </Row>
    </Rowset>
</Rowsets>

我的问题是在该领域我不想连接坦克,如果它重复。

样品应该是:

<Row>
                <Material>1000002754</Material>
                <Description>43 Bulk</Description>
                <Value>T515||T517||</Value>
            </Row>

我尝试了各种组合,却无法实现。任何人都可以帮忙吗?

2 个答案:

答案 0 :(得分:1)

如果XML越来越大,基于密钥的解决方案(使用xslt-1.0)会更好。

但是为了解决大多数情况下的解决方案,只有具有独特的Tank值。您可以添加两个模板:

<xsl:template match="item" mode="tank" />
<xsl:template match="item[not(Material = preceding::item/Material and Tank =  preceding::item/Tank)]" mode="tank" >
    <xsl:value-of select="Tank"/>
    <xsl:text>||</xsl:text>
</xsl:template>

这会忽略具有相同材质和相同Tank值的任何项目。

并应用此模板替换<Value>中的for-each循环:

<xsl:apply-templates select="$materials[Material=current()/Material ]" mode="tank" />

因此请尝试:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output encoding="UTF-8" indent="yes" method="xml" version="1.0"/>
    <xsl:template match="/">
        <Rowsets>
            <Rowset>
                <xsl:variable name="materials" select=".//item[Tank!='RECV' and Tank!='PARK'] "/>
                <xsl:for-each select="$materials">
                    <xsl:if test="generate-id(.)= generate-id($materials[Material=current()/Material])">
                        <Row>
                            <Material>
                                <xsl:value-of select="Material"/>
                            </Material>
                            <Description>
                                <xsl:value-of select="Description"/>
                            </Description>
                            <Value>
                                <xsl:apply-templates select="$materials[Material=current()/Material ]" mode="tank" />
                            </Value>
                        </Row>
                    </xsl:if>
                </xsl:for-each>
            </Rowset>
        </Rowsets>
    </xsl:template>
    <xsl:template match="item" mode="tank" />
    <xsl:template match="item[not(Material = preceding::item/Material and Tank =  preceding::item/Tank)]" mode="tank" >
        <xsl:value-of select="Tank"/>
        <xsl:text>||</xsl:text>
    </xsl:template>

</xsl:stylesheet>

将生成以下输出:

<Rowsets>
  <Rowset>
    <Row>
      <Material>1000000079</Material>
      <Description>330 Bulk</Description>
      <Value>T123||</Value>
    </Row>
    <Row>
      <Material>1000000196</Material>
      <Description>340R Bulk</Description>
      <Value>T700||</Value>
    </Row>
    <Row>
      <Material>1000002754</Material>
      <Description>43 Bulk</Description>
      <Value>T515||T517||</Value>
    </Row>
  </Rowset>
</Rowsets>

答案 1 :(得分:1)

对于XSLT 1.0,您希望使用名为Muenchian grouping的内容。我假设你可能想要保留替代描述并简化你的XSLT:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output encoding="UTF-8" indent="yes" method="xml" version="1.0"/>

  <xsl:template match="/">
    <xsl:variable name="materials" select="BATCHES/item[Tank!='RECV' and Tank!='PARK']"/>

    <Rowsets>
      <Rowset>
        <xsl:for-each select="$materials[not(Material=preceding-sibling::item/Material)]">
          <Row>
            <xsl:variable name="items" select="//item[Material=current()/Material]"/>
            <xsl:variable name="distinct-descriptions" select="$items[not(Description=preceding-sibling::item/Description)]"/>
            <xsl:variable name="distinct-tanks" select="$items[not(Tank=preceding-sibling::item/Tank)]"/>

            <Material><xsl:value-of select="Material"/></Material>
            <Description>
              <xsl:for-each select="$distinct-descriptions">
                  <xsl:if test="position() != 1">||</xsl:if>
                  <xsl:value-of select="Description"/>
              </xsl:for-each>
            </Description>
            <Value>
              <xsl:for-each select="$distinct-tanks">
                <xsl:if test="position() != 1">||</xsl:if>
                <xsl:value-of select="Tank"/>
              </xsl:for-each>
            </Value>
          </Row>
        </xsl:for-each>
      </Rowset>
    </Rowsets>
  </xsl:template>
</xsl:stylesheet>

这样做你喜欢什么吗?