删除XSLT中的重复属性

时间:2012-08-03 06:22:30

标签: xslt-2.0

我理解这是多次发布的一个常见问题,但不幸的是,我无法找到任何提议方法的确切解决方案:

以下是我的XML的样子:

<root>
  <parent>
    <table>
    <attr ......>
       <type t="enumone">
       <info>
        <name .....>
       </info>
    </attr>

    <attr>
        <type t="int">
        <range min="1" max="255"/>
         </type>
         <info>
        <name .....>
       </info>
    </attr>

    <attr>
        <type t="string">
         <info>
        <name .....>
       </info>
    </attr> 
    <attr ......>
       <type t="enumtwo">
       <info>
        <name .....>
       </info>
    </attr>

    <attr>
        <type t="float">
        <range min="1.0" max="25.5"/>
         </type>
         <info>
        <name .....>
       </info>
    </attr>

    <attr>
        <type t="int">
         <info>
        <name .....>
       </info>
    </attr> 


    <attr>
        <type t="enumone">
         <info>
        <name .....>
       </info>
    </attr> 
    <attr>
        <type t="enumthree">
         <info>
        <name .....>
       </info>
    </attr> 
    <attr>
        <type t="enumone">
         <info>
        <name .....>
       </info>
    </attr> 
    </parent>
 </root>

目的是使用XSLT从“type”元素中检索一次属性“@t”:

Using for-each-group:
<xsl-template match="/root/parent">
  <xsl:for-each select="table">
    <xsl:for-each-group select="//type" group-by="@t">
       <xsl:copy-of select="current-group( )[1]"/>
    </xsl:for-each-group>
  </xsl:for-each>
<xsl-template>

但我没有输出!我相信有些瑕疵。

使用distinct-values():

<xsl:for-each select="distinct-values(type/@t)">
<xsl:sort/>
<xsl:value-of select="."/> <xsl:call-template name="newline"/>
</xsl:for-each>

仍然没有理想的输出。

预期输出为:

enumone
int
string
enumtwo
float
enumthree

感谢这方面的任何帮助。

2 个答案:

答案 0 :(得分:2)

输入样本不是格式良好的XML,但如果您真的只想要所有t元素的不同type属性值,那么

<xsl:template match="/">
  <xsl:value-of select="distinct-values(//type/@t)" separator="&#10;"/>
</xsl:template>

足以使用XSLT 2.0。

如果您还想要对不同的值进行排序,那么请执行

<xsl:template match="/">
  <xsl:value-of separator="&#10;">
    <xsl:perform-sort select="distinct-values(//type/@t)">
       <xsl:sort select="."/>
    </xsl:perform-sort>
  </xsl:value-of>
</xsl:template>

提供一个完整的例子,输入为

<root>
  <foo>
    <type t="int"/>
  </foo>
  <bar>
    <type t="enum"/>
  </bar>
  <foobar>
     <foo>
        <type t="enum">
           <x/>
        </type>
     </foo>
   </foobar>
   <foo>
      <type t="string"/>
   </foo>
</root>

样式表

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="text"/>

<xsl:template match="/">
  <xsl:value-of separator="&#10;">
    <xsl:perform-sort select="distinct-values(//type/@t)">
       <xsl:sort select="."/>
    </xsl:perform-sort>
  </xsl:value-of>
</xsl:template>

</xsl:stylesheet>

输出

enum
int
string

答案 1 :(得分:0)

只需将您的代码修改为

<xsl:template match="/">
    <xsl:for-each-group select="//type" group-by="@t">
       <xsl:copy-of select="current-group( )[1]"/>
    </xsl:for-each-group>
</xsl:template>

完整转型

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:template match="/">
    <xsl:for-each-group select="//type" group-by="@t">
       <xsl:copy-of select="current-group( )[1]"/>
    </xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>

应用于格式良好的XML文档

<root>
  <foo>
    <type t="int"/>
  </foo>
  <bar>
    <type t="enum"/>
  </bar>
  <foobar>
     <foo>
        <type t="enum">
           <x/>
        </type>
     </foo>
   </foobar>
   <foo>
      <type t="string"/>
   </foo>
</root>

产生了正确的结果

<type t="int"/>
<type t="enum"/>
<type t="string"/>