2011-10-03 87 views
1

我在使用XSLT 1.0获取唯一列表时遇到了一个典型问题。使用XSLT 1.0获取唯一值(不使用XSL:Key)

样品XSLT:

<xsl:if test="$tempVar = 'true'"> 
    <xsl:variable name="filePath" select="document($mPath)" /> 
    // Do something 
    // I can't implement this using "Muenchian Method". 
    // Since, I can't declare <xsl:key> inside of <xsl:if> 
    // There is no chance to declare <xsl:key> on top. 
    // I should get unique list from here only 
</xsl:if> 

文件路径变量将包含XML如下: -

<Root> 
    <Data id="102"> 
     <SubData> 
      <Info code="abc">Information 102</Info> 
     </SubData> 
    </Data> 
    <Data id="78"> 
     <SubData> 
      <Info code="def">Information 78</Info> 
     </SubData> 
    </Data> 
    <Data id="34"> 
     <SubData> 
      <Info code="abc">Information 34</Info> 
     </SubData> 
    </Data> 
    <Data id="55"> 
     <SubData> 
      <Info code="xyz">Information 55</Info> 
     </SubData> 
    </Data> 
    <Data id="86"> 
     <SubData> 
      <Info code="def">Information 86</Info> 
     </SubData> 
    </Data> 
    <Data id="100"> 
     <SubData> 
      <Info code="xyz">Information 100</Info> 
     </SubData> 
    </Data> 
</Root> 

输出:独特的代码列表应该

abc 
def 
xyz 

感谢

+0

你声称键和Muenchian分组不能用于你的情况 - 这是不正确的。你现在将学习如何去做。 :)为问+1 :) –

回答

2
<xsl:if test="$tempVar = 'true'"> 
    <xsl:variable name="filePath" select="document($mPath)" /> 
    // Do something 
    // I can't implement this using "Muenchian Method". 
    // Since, I can't declare <xsl:key> inside of <xsl:if> 
    // There is no chance to declare <xsl:key> on top. 
    // I should get unique list from here only 
</xsl:if> 

这是不正确的,一个不能在这样的情况下使用<xsl:key>key()功能:

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

<xsl:key name="kcodeByVal" match="@code" use="."/> 

<xsl:variable name="tempVar" select="'true'"/> 

<xsl:variable name="vrtfFilePath"> 
    <Root> 
     <Data id="102"> 
      <SubData> 
       <Info code="abc">Information 102</Info> 
      </SubData> 
     </Data> 
     <Data id="78"> 
      <SubData> 
       <Info code="def">Information 78</Info> 
      </SubData> 
     </Data> 
     <Data id="34"> 
      <SubData> 
       <Info code="abc">Information 34</Info> 
      </SubData> 
     </Data> 
     <Data id="55"> 
      <SubData> 
       <Info code="xyz">Information 55</Info> 
      </SubData> 
     </Data> 
     <Data id="86"> 
      <SubData> 
       <Info code="def">Information 86</Info> 
      </SubData> 
     </Data> 
     <Data id="100"> 
      <SubData> 
       <Info code="xyz">Information 100</Info> 
      </SubData> 
     </Data> 
    </Root> 
</xsl:variable> 

<xsl:variable name="vfilePath" 
     select="ext:node-set($vrtfFilePath)"/> 

<xsl:template match="/"> 
    <xsl:if test="$tempVar = 'true'"> 
    <xsl:for-each select="$vfilePath"> 
     <xsl:for-each select= 
     "*/*/*/Info/@code 
        [generate-id() 
        = 
        generate-id(key('kcodeByVal',.)[1]) 
        ] 
     "> 
     <xsl:value-of select="concat(.,' ')"/> 
     </xsl:for-each> 
    </xsl:for-each> 
    </xsl:if> 
</xsl:template> 

</xsl:stylesheet> 

当这种转换应用于任何XML文档(不在这个例子中使用),想要的,正确的结果产生

abc def xyz 
+0

嗨Dimitre,我也在等你的解决方案。最后你已经发布。感谢它。我有一个小小的疑问:** ** **这个LOC究竟做了什么?请解释。 **注意:**对于我的实例,** XML **不适用于整个** XSLT **。 ** XML **仅作为** IF **条件获取。 –

+0

@SivaCharan:一个''只能是一个全局指令 - 这完全不意味着它不能在条件指令中的任何位置使用'key()'函数进行引用。 @迈克尔凯是正确的,你需要阅读关键和需要了解他们。现在你没有这方面的知识和理解,任何答案的主要优点都必须让你意识到这个事实。因为没有这些必要的知识,你甚至无法理解任何使用密钥的解决方案。 –

+0

@SivaCharan:特别指出:**' **定义一个键(索引),给它一个名字,指定要索引的节点('@ code')以及应该用作索引(键)值的值 - 在这种情况下,匹配节点的字符串值。这只是一个定义 - 它不会导致任何索引,直到一个'key()'函数引用这个特定的键。只有这样才能完成索引 - 在*当前文档*上。请阅读一本好的XSLT书。 –

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

    <xsl:template match="/"> 
     <xsl:apply-templates select="//Data[ 
          not(
           */Info/@code = preceding-sibling::Data/*/Info/@code 
          ) 
         ]/*/Info/@code"/> 
    </xsl:template> 

    <xsl:template match="@*"> 
     <xsl:value-of select="."/> 
     <xsl:text>&#xD;</xsl:text> 
    </xsl:template> 

</xsl:stylesheet> 
+0

感谢基里尔..这也工作。但我会使用Dimitre解决方案。 +1为好的答案。 –

1

你的理由不使用Muenchian方法或XSL:关键是虚假的。它会很好地工作。您可能没有明白,当您声明一个关键定义时,它不是特定于某个特定的源文档,它允许您针对任何源文档使用key()函数。

+0

如果没有错,我们不能在** **内声明** **。由于我正在获取if条件中的xml(即文档)。请提出建议。 –