从XSLT中的连接字符串中删除重复值

时间:2017-02-06 14:25:39

标签: xslt xslt-1.0

我想从连接字符串中删除重复值。

输入是:

 <?xml version="1.0" encoding="ISO-8859-1"?>    
    <QL>
        <QITEM>
            <SERIAL>123</SERIAL>
            <PROD_NAME>User/Device</PROD_NAME>
        </QITEM>
        <QITEM>
            <SERIAL>123</SERIAL>
            <PROD_NAME>User/Dev</PROD_NAME>
        </QITEM>
        <QITEM>
            <SERIAL>123</SERIAL>
            <PROD_NAME>User/Device</PROD_NAME>
        </QITEM>
        <QITEM>
            <SERIAL>1234</SERIAL>
            <PROD_NAME>45 Mbps</PROD_NAME>
        </QITEM>
    </QL>
     <QL>
        <QITEM>
            <SERIAL>123</SERIAL>
            <PROD_NAME>User/Device</PROD_NAME>
        </QITEM>
        <QITEM>
            <SERIAL>123</SERIAL>
            <PROD_NAME>User/Dev</PROD_NAME>
        </QITEM>
        <QITEM>
            <SERIAL>123</SERIAL>
            <PROD_NAME>User/Device</PROD_NAME>
        </QITEM>
        <QITEM>
            <SERIAL>1234</SERIAL>
            <PROD_NAME>45 Mbps</PROD_NAME>
        </QITEM>
    </QL>

我想连接值,输出应该是:

<Result>
  <SERIAL>123,1234</SERIAL>
  <PROD_NAME>User/Dev,User/Device,45 Mbps</PROD_NAME>
</Result>
<Result>
  <SERIAL>123,1234</SERIAL>
  <PROD_NAME>User/Dev,User/Device,45 Mbps</PROD_NAME>
</Result>

到目前为止,我已尝试使用以下模板实现此目的:

<xsl:template name="join">
    <xsl:param name="list"/>
    <xsl:param name="separator"/>
    <xsl:for-each select="$list">
      <xsl:value-of select="."/>
      <xsl:if test="position() != last()">
        <xsl:value-of select="$separator"/>
      </xsl:if>
    </xsl:for-each>
</xsl:template>

这是用逗号分隔的值 但我希望得到独特的价值观。

1 个答案:

答案 0 :(得分:1)

纯XSLT 1.0中的唯一/不同值最好通过使用Muenchian Method分组来实现。

在下面的示例中,我们为每个要包含一组的项目创建xsl:key

例如,键serial是一组使用自身值作为分组键的所有SERIAL元素。

然后我们遍历每个组(xsl:for-each)并仅选择该组的第一次出现。

完整示例......

XML输入

<QL>
    <QITEM>
        <SERIAL>123</SERIAL>
        <PROD_NAME>User/Device</PROD_NAME>
    </QITEM>
    <QITEM>
        <SERIAL>123</SERIAL>
        <PROD_NAME>User/Dev</PROD_NAME>
    </QITEM>
    <QITEM>
        <SERIAL>123</SERIAL>
        <PROD_NAME>User/Device</PROD_NAME>
    </QITEM>
    <QITEM>
        <SERIAL>1234</SERIAL>
        <PROD_NAME>45 Mbps</PROD_NAME>
    </QITEM>
</QL>

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="*"/>

  <xsl:key name="serial" match="SERIAL" use="."/>
  <xsl:key name="prodname" match="PROD_NAME" use="."/>

  <xsl:template match="/*">
    <Result>
      <SERIAL>
        <xsl:for-each select="QITEM/SERIAL[count(.|key('serial',.)[1])=1]">
          <xsl:if test="position() > 1">,</xsl:if>
          <xsl:value-of select="."/>
        </xsl:for-each>
      </SERIAL>
      <PROD_NAME>
        <xsl:for-each select="QITEM/PROD_NAME[count(.|key('prodname',.)[1])=1]">
          <xsl:if test="position() > 1">,</xsl:if>
          <xsl:value-of select="."/>
        </xsl:for-each>
      </PROD_NAME>
    </Result>
  </xsl:template>

</xsl:stylesheet>

XML输出

<Result>
   <SERIAL>123,1234</SERIAL>
   <PROD_NAME>User/Device,User/Dev,45 Mbps</PROD_NAME>
</Result>

<强>更新

我不确定我是否完全理解您的更新,但我认为您可以使用生成的祖先QL的ID创建复合键。

XML输入(包含在doc中以使其格式正确。)

<doc>
    <QL>
        <QITEM>
            <SERIAL>123</SERIAL>
            <PROD_NAME>User/Device</PROD_NAME>
        </QITEM>
        <QITEM>
            <SERIAL>123</SERIAL>
            <PROD_NAME>User/Dev</PROD_NAME>
        </QITEM>
        <QITEM>
            <SERIAL>123</SERIAL>
            <PROD_NAME>User/Device</PROD_NAME>
        </QITEM>
        <QITEM>
            <SERIAL>1234</SERIAL>
            <PROD_NAME>45 Mbps</PROD_NAME>
        </QITEM>
    </QL>
    <QL>
        <QITEM>
            <SERIAL>123</SERIAL>
            <PROD_NAME>User/Device</PROD_NAME>
        </QITEM>
        <QITEM>
            <SERIAL>123</SERIAL>
            <PROD_NAME>User/Dev</PROD_NAME>
        </QITEM>
        <QITEM>
            <SERIAL>123</SERIAL>
            <PROD_NAME>User/Device</PROD_NAME>
        </QITEM>
        <QITEM>
            <SERIAL>1234</SERIAL>
            <PROD_NAME>45 Mbps</PROD_NAME>
        </QITEM>
    </QL>
</doc>

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="*"/>

  <xsl:key name="serial" match="SERIAL" use="concat(generate-id(ancestor::QL),'|',.)"/>
  <xsl:key name="prodname" match="PROD_NAME" use="concat(generate-id(ancestor::QL),'|',.)"/>

  <xsl:template match="QL">
    <Result>
      <SERIAL>        
        <xsl:for-each select="QITEM/SERIAL[count(.|key('serial',concat(generate-id(ancestor::QL),'|',.))[1])=1]">
          <xsl:if test="position() > 1">,</xsl:if>
          <xsl:value-of select="."/>
        </xsl:for-each>
      </SERIAL>
      <PROD_NAME>
        <xsl:for-each select="QITEM/PROD_NAME[count(.|key('prodname',concat(generate-id(ancestor::QL),'|',.))[1])=1]">
          <xsl:if test="position() > 1">,</xsl:if>
          <xsl:value-of select="."/>
        </xsl:for-each>
      </PROD_NAME>
    </Result>
  </xsl:template>

</xsl:stylesheet>

XML输出

<Result>
   <SERIAL>123,1234</SERIAL>
   <PROD_NAME>User/Device,User/Dev,45 Mbps</PROD_NAME>
</Result>
<Result>
   <SERIAL>123,1234</SERIAL>
   <PROD_NAME>User/Device,User/Dev,45 Mbps</PROD_NAME>
</Result>