整合数据并排除XSLT中的重复项

时间:2012-08-13 14:14:57

标签: xslt

我有一个传入的XML文档,其中包含以下形式的一些节点:

<userOptions>
  <userOption>
      <type>A</type>
      <plan>
          <frequency>MONTHLY</frequency>
      </plan>
      <method>
          <methodType>X1</methodType>
      </method>
  </userOption>

  <userOption>
      <type>B</type>
      <plan>
          <frequency>QUARTERLY</frequency>
      </plan>
      <method>
          <methodType>X2</methodType>
      </method>
  </userOption>

  <userOption>
    <type>A</type>
      <plan>
        <frequency>3MONTH</frequency>
      </plan>
      <method>
        <methodType>X1-B</methodType>
      </method>
  </userOption>
</userOptions>

我需要整合并将其转换为看起来像这样的东西:

<userOptions>
    <userOption>
      <type>A</type>
      <plan>
         <frequency>3MONTH</frequency>
         <methodType>X1-B</methodType>
      </plan>
      <plan>
         <frequency>MONTHLY</frequency>
         <methodType>X1</methodType>
      </plan>
    <userOption>
    <userOption>
      <type>B</type>
      <plan>
         <frequency>QUARTERLY</frequency>
         <methodType>X2</methodType>
      </plan>
    <userOption>
</userOptions>

我目前的转型如下:

<userOptions>
    <xsl:for-each select="//userOptions">
        <userOption>
            <type>
                <xsl:value-of select="type" />
            </type>

            <xsl:variable name="currentType" select="type"/>
            <xsl:message><xsl:value-of select="$currentType"/></xsl:message>

            <xsl:variable name="currentMethod" select="method/methodType"/>
            <xsl:message><xsl:value-of select="$currentMethod/></xsl:message>

            <plan>
                <frequency>
                    <xsl:value-of select="plan/frequency" />
                </frequency>
                <method>
                    <xsl:value-of select="method/methodType" />
                </method>
            </plan>

            <xsl:for-each select="../userOptions[type=$currentType and method/methodType!=$currentMethod]">

                <plan>
                    <frequency>
                        <xsl:value-of select="plan/frequency" />
                    </frequency>
                    <method>
                        <xsl:value-of select="method/methodType" />
                    </method>
                </plan>

            </xsl:for-each>
        </userOption>
    </xsl:for-each>
</userOptions>

问题是我得到重复,例如:

    <userOption>
      <type>A</type>
      <plan>
         <frequency>3MONTH</frequency>
         <methodType>X1-B</methodType>
      </plan>
      <plan>
         <frequency>MONTHLY</frequency>
         <methodType>X1</methodType>
      </plan>
    <userOption>
    <userOption>
      <type>A</type>
      <plan>
         <frequency>MONTHLY</frequency>
         <methodType>X1</methodType>
      </plan>
      <plan>
         <frequency>3MONTH</frequency>
         <methodType>X1-B</methodType>
      </plan>
    <userOption>

我不确定如何使用匹配的type和不同的methodType合并记录,但也要避免重复。

1 个答案:

答案 0 :(得分:1)

这是Muenchian grouping方法的一个很好的候选者:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:key name="user-type" match="userOption" use="type" />
  <xsl:template match="/">
    <userOptions>
      <!-- this for-each iterates over a node set consisting of just
      the *first* userOption element for each type -->
      <xsl:for-each select="userOptions/userOption[count( . | key('user-type', type)[1]) = 1]">
        <userOption>
          <xsl:copy-of select="type" />
          <!-- apply templates for all userOption elements of this type
          (including the one we are currently for-eaching over) -->
          <xsl:apply-templates select="key('user-type', type)" />
        </userOption>
      </xsl:for-each>
    </userOptions>
  </xsl:template>

  <xsl:template match="userOption">
    <plan>
      <frequency>
        <xsl:value-of select="plan/frequency" />
      </frequency>
      <method>
        <xsl:value-of select="method/methodType" />
      </method>
    </plan>
  </xsl:template>
</xsl:stylesheet>

这是定义节点组的一种很好的方法,然后通过小心使用键,每个组而不是每个节点迭代一次。如果你可以使用XSLT 2,那么语言(<xsl:for-each-group>)内置了一个更直接的方法,但在XSLT 1中没有。