删除重复值并在XSLT中计算它们

时间:2015-12-09 16:53:29

标签: xml xslt duplicates

我需要根据需要转换为所需的输出。

这是我的输入XML:

<ns0:SegmentationResponse xmlns:ns0 = "http://asdf.com/BTS/BusinessDashboard/SegmentationResponse/2013/08">

    <Segmentation>

        <segmentationName>PRODUCTION</segmentationName>

        <SegmentationSubType>

            <segmentationSubTypeName>Advisors</segmentationSubTypeName>

            <Value>

                <valueTypeName/>

                <ValueList>

                    <slno>1</slno>
                    <name>JOSE CRUZ</name>
                    <value>0</value>
                </ValueList>

                <ValueList>
                    <slno>2</slno>
                    <name>JOSE CRUZ</name>
                    <value>0</value>
                </ValueList>

                <ValueList>
                    <slno>3</slno>
                    <name>JOSE CRUZ</name>
                    <value>0</value>
                </ValueList>

                <ValueList>
                    <slno>2</slno>
                    <name>sanga</name>
                    <value>0</value>
                </ValueList>

                <ValueList>
                    <slno>3</slno>
                    <name>sanga</name>
                    <value>0</value>
                </ValueList>

        </Value>
        </SegmentationSubType>
        <SegmentationSubType>
            <segmentationSubTypeName>Accounts</segmentationSubTypeName>
            <Value>
                <valueTypeName/>

                <ValueList>
                    <slno>1</slno>
                    <name>sure</name>
                    <value>3</value>
                </ValueList>

                <ValueList>
                    <slno>2</slno>
                    <name>sure</name>
                    <value>3</value>
                </ValueList>

                <ValueList>
                    <slno>3</slno>
                    <name>sure</name>
                    <value>3</value>
                </ValueList>

                <ValueList>
                    <slno>393</slno>
                    <name>2013090436641882</name>
                    <value>7</value>
                </ValueList>

                <ValueList>
                    <slno>399</slno>
                    <name>2013090436641882</name>
                    <value>7</value>
                </ValueList>

                <ValueList>
                    <slno>400</slno>
                    <name>2013090436641882</name>
                    <value>7</value>
                </ValueList>

                <ValueList>
                    <slno>401</slno>
                    <name>2013090436647677</name>
                    <value>65</value>
                </ValueList>

                <ValueList>
                    <slno>402</slno>
                    <name>2013090436647677</name>
                    <value>65</value>
                </ValueList>

                <ValueList>
                    <slno>499</slno>
                    <name>2013090436663871</name>
                    <value>0</value>
                </ValueList>

                <ValueList>
                    <slno>500</slno>
                    <name>2013090436663871</name>
                    <value>1</value>
                </ValueList>

                <ValueList>
                    <slno>501</slno>
                    <name>2013090436663871</name>
                    <value>1</value>
                </ValueList>

            </Value>

        </SegmentationSubType>

    </Segmentation>

</ns0:SegmentationResponse>

我想要输出如下(删除重复的名称并计算重复项并动态生成元素)。

<ns0:SegmentationResponse xmlns:ns0="http://asdf.com/BTS/BusinessDashboard/SegmentationResponse/2013/08">

    <Segmentation>

        <segmentationName>PRODUCTION</segmentationName>

        <SegmentationSubType>

            <segmentationSubTypeName>Advisors</segmentationSubTypeName>

            <Value>

                <valueTypeName/>

                <ValueList>
                    <name>JOSE CRUZ</name>
                    <value>3</value>
                </ValueList>

                <ValueList>
                    <name>sanga</name>
                    <value>2</value>
                </ValueList>

            </Value>


        </SegmentationSubType>

        <SegmentationSubType>

            <segmentationSubTypeName>Accounts</segmentationSubTypeName>

            <Value>

                <valueTypeName/>

                <ValueList>
                    <name>sure</name>
                    <value>3</value>
                </ValueList>

                <ValueList>
                    <name>2013090436641882</name>
                    <value>3</value>
                </ValueList>

                <ValueList>
                    <name>2013090436647677</name>
                    <value>2</value>
                </ValueList>

                <ValueList>
                <name>2013090436663871</name>
                    <value>3</value>
                </ValueList>

            </Value>

        </SegmentationSubType>

    </Segmentation>

</ns0:SegmentationResponse>

这是我的xsl,它计算所有元素。但它需要按照上面的示例xml中的规定进行分组。任何人都可以提供帮助吗?

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns0="http://asdf.com/BTS/BusinessDashboard/SegmentationResponse/2013/08">

    <xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="ns0:SegmentationResponse/Segmentation/SegmentationSubType">
        <xsl:element name="segmentationSubTypeName">

            <xsl:call-template name="calculate">
                <xsl:with-param name="namecount" select="count(./Value/ValueList)"/>
                <xsl:with-param name="name" select="./Value/ValueList/name"/>
            </xsl:call-template>
        </xsl:element>
    </xsl:template>

    <xsl:template name="calculate">
        <xsl:param name="namecount"/>
        <xsl:param name="name"/>
        <xsl:element name="Value">
            <xsl:element name="ValueList">
                <xsl:element name="name">
                    <xsl:value-of select="$name"/>
                </xsl:element>
                <xsl:element name="Value">
                    <xsl:value-of select="$namecount"/>
                </xsl:element>
            </xsl:element>
        </xsl:element>
    </xsl:template>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

1 个答案:

答案 0 :(得分:0)

以下是使用xsl:key的一个选项(此处的工作示例:http://xsltransform.net/ncdD7mw/1)...

XML输入

<ns0:SegmentationResponse xmlns:ns0="http://asdf.com/BTS/BusinessDashboard/SegmentationResponse/2013/08">
    <Segmentation>
        <segmentationName>PRODUCTION</segmentationName>
        <SegmentationSubType>
            <segmentationSubTypeName>Advisors</segmentationSubTypeName>
            <Value>
                <valueTypeName/>
                <ValueList>
                    <slno>1</slno>
                    <name>JOSE CRUZ</name>
                    <value>0</value>
                </ValueList>
                <ValueList>
                    <slno>2</slno>
                    <name>JOSE CRUZ</name>
                    <value>0</value>
                </ValueList>
                <ValueList>
                    <slno>3</slno>
                    <name>JOSE CRUZ</name>
                    <value>0</value>
                </ValueList>
                <ValueList>
                    <slno>2</slno>
                    <name>sanga</name>
                    <value>0</value>
                </ValueList>
                <ValueList>
                    <slno>3</slno>
                    <name>sanga</name>
                    <value>0</value>
                </ValueList>
            </Value>
        </SegmentationSubType>
        <SegmentationSubType>
            <segmentationSubTypeName>Accounts</segmentationSubTypeName>
            <Value>
                <valueTypeName/>
                <ValueList>
                    <slno>1</slno>
                    <name>sure</name>
                    <value>3</value>
                </ValueList>
                <ValueList>
                    <slno>2</slno>
                    <name>sure</name>
                    <value>3</value>
                </ValueList>
                <ValueList>
                    <slno>3</slno>
                    <name>sure</name>
                    <value>3</value>
                </ValueList>
                <ValueList>
                    <slno>393</slno>
                    <name>2013090436641882</name>
                    <value>7</value>
                </ValueList>
                <ValueList>
                    <slno>399</slno>
                    <name>2013090436641882</name>
                    <value>7</value>
                </ValueList>
                <ValueList>
                    <slno>400</slno>
                    <name>2013090436641882</name>
                    <value>7</value>
                </ValueList>
                <ValueList>
                    <slno>401</slno>
                    <name>2013090436647677</name>
                    <value>65</value>
                </ValueList>
                <ValueList>
                    <slno>402</slno>
                    <name>2013090436647677</name>
                    <value>65</value>
                </ValueList>
                <ValueList>
                    <slno>499</slno>
                    <name>2013090436663871</name>
                    <value>0</value>
                </ValueList>
                <ValueList>
                    <slno>500</slno>
                    <name>2013090436663871</name>
                    <value>1</value>
                </ValueList>
                <ValueList>
                    <slno>501</slno>
                    <name>2013090436663871</name>
                    <value>1</value>
                </ValueList>
            </Value>
        </SegmentationSubType>
    </Segmentation>
</ns0:SegmentationResponse>

XSLT 1.0

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

  <!--Create key based on segmentation sub type and name.-->
  <xsl:key name="valsBySubtype" match="ValueList" use="name"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Value">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()[not(self::ValueList)]|
        ValueList[count(.|key('valsBySubtype',name)[1])=1]"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="ValueList">
    <xsl:copy>
      <xsl:apply-templates select="@*|name|value"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="ValueList/value">
    <value>
      <xsl:value-of select="count(key('valsBySubtype',../name))"/>
    </value>
  </xsl:template>

</xsl:stylesheet>

XML输出

<ns0:SegmentationResponse xmlns:ns0="http://asdf.com/BTS/BusinessDashboard/SegmentationResponse/2013/08">
   <Segmentation>
      <segmentationName>PRODUCTION</segmentationName>
      <SegmentationSubType>
         <segmentationSubTypeName>Advisors</segmentationSubTypeName>
         <Value>
            <valueTypeName/>
            <ValueList>
               <name>JOSE CRUZ</name>
               <value>3</value>
            </ValueList>
            <ValueList>
               <name>sanga</name>
               <value>2</value>
            </ValueList>
         </Value>
      </SegmentationSubType>
      <SegmentationSubType>
         <segmentationSubTypeName>Accounts</segmentationSubTypeName>
         <Value>
            <valueTypeName/>
            <ValueList>
               <name>sure</name>
               <value>3</value>
            </ValueList>
            <ValueList>
               <name>2013090436641882</name>
               <value>3</value>
            </ValueList>
            <ValueList>
               <name>2013090436647677</name>
               <value>2</value>
            </ValueList>
            <ValueList>
               <name>2013090436663871</name>
               <value>3</value>
            </ValueList>
         </Value>
      </SegmentationSubType>
   </Segmentation>
</ns0:SegmentationResponse>

如果你能够使用XSLT 2.0,那么这是另一个选择...

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

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Value">
    <xsl:copy>
      <xsl:apply-templates select="@*|node() except ValueList"/>
      <xsl:for-each-group select="ValueList" group-by="name">
        <ValueList>
          <name><xsl:value-of select="current-grouping-key()"/></name>
          <value><xsl:value-of select="count(current-group())"/></value>
        </ValueList>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>