按值排序元素并删除重复项

时间:2011-04-20 07:31:18

标签: xslt sorting select

我有以下输入:

<?xml version="1.0" encoding="utf-8"?>
<NewTerms>
  <newTerm>XPath</newTerm>
  <newTerm>AutoValue</newTerm>
  <newTerm>XPath</newTerm>
  <newTerm>context</newTerm>
  <newTerm>AutoValue</newTerm>
  <newTerm>language files</newTerm>
   <newTerm>AutoValue</newTerm>
  <newTerm>.NET</newTerm>
  <newTerm>XPath</newTerm>
</NewTerms>

我想对它进行排序,它与以下功能完美配合:

  <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>

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

</xsl:stylesheet>

问题是我(显然)得到一个排序的输出列表,其中重复的元素具有相同的值(例如XPath,AutoValue)。我想要排序列表没有重复的值。也就是说,我希望在排序的XML输出中只使用一次值。

请提出任何建议?

2 个答案:

答案 0 :(得分:2)

此样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kNewTermByValue" match="newTerm" use="."/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="NewTerms">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates
             select="newTerm[count(.|key('kNewTermByValue',.)[1])=1]">
                <xsl:sort/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

输出:

<NewTerms xp_0:noNamespaceSchemaLocation="../XSD\CC-CustomDocuTags.xsd" xmlns:xp_0="http://www.w3.org/2001/XMLSchema-instance">
    <newTerm>.NET</newTerm>
    <newTerm>AutoValue</newTerm>
    <newTerm>context</newTerm>
    <newTerm>EPF</newTerm>
    <newTerm>language files</newTerm>
    <newTerm>XPath</newTerm>
</NewTerms>

注意:不要将属性和子项排在一起,因为输出子项后无法输出属性。

答案 1 :(得分:1)

您应该过滤排序的选择:

<xsl:template match="@*|node()[not(preceding::node()=.)]">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()">
            <xsl:sort select="."/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

它会给你想要的输出:

<?xml version="1.0"?>
<NewTerms>
    <newTerm>.NET</newTerm>
    <newTerm>AutoValue</newTerm>AutoValueAutoValue
    <newTerm>EPF</newTerm>
    <newTerm>XPath</newTerm>XPathXPath
    <newTerm>context</newTerm>
    <newTerm>language files</newTerm>
</NewTerms>