2010-04-29 53 views
5

好吧,我有这个XMLXSL唯一值

<roots> 
<root> 
    <name>first</name> 
    <item type='test'><something>A</something></item> 
    <item type='test'><something>B</something></item> 
    <item type='test'><something>C</something></item> 
    <item type='test'><something>A</something></item> 
    <item type='other'><something>A</something></item> 
    <item type='test'><something>B</something></item> 
    <item type='other'><something>D</something></item> 

</root> 
<root> 
<name>second</name> 
    <item type='test'><something>E</something></item> 
    <item type='test'><something>B</something></item> 
    <item type='test'><something>F</something></item> 
    <item type='test'><something>A</something></item> 
    <item type='other'><something>A</something></item> 
    <item type='test'><something>B</something></item> 
    <item type='other'><something>D</something></item> 

</root> 

</roots> 

现在我需要得到各根节点的唯一值到目前为止,我已经

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output indent="yes" method="text"/> 
    <xsl:key name="item-by-value" match="something" use="."/> 
    <xsl:key name="rootkey" match="root" use="name"/> 

    <xsl:template match="/"> 
    <xsl:for-each select="key('rootkey','second')"> 
     <xsl:for-each select="item/something"> 
     <xsl:if test="generate-id() = generate-id(key('item-by-value', normalize-space(.)))"> 
      <xsl:value-of select="."/> 
     </xsl:if> 
     </xsl:for-each> 
    </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

如果我使用“第一”关键只得到第一根我得到一个好的结果ABCD

我怎么过,如果我使用“第二”我只得到EF但需要得到的结果是ABDFE

+0

很好的问题(+1)。查看我的答案,获得完整和正确的解决方案。 :) – 2010-04-30 01:04:05

回答

2

我得到EBFAD对你的xsl进行了一些修改。关键在于,如果您使用密钥在给定根元素下查找包含此内容的第一个节点,则该密钥需要特定于根元素。我改变了xsl:key到:

<xsl:key name="item-by-value" match="something" 
use="concat(normalize-space(.), ' ', generate-id(./ancestor::root))"/> 

然后xsl:if测试变为:

<xsl:if test="generate-id() = generate-id(key('item-by-value', 
        concat(normalize-space(.), ' ', generate-id(./ancestor::root))))"> 
0

我觉得你很亲密。但是,你只需要拥有正确的根作为父项目按值键的第一个值:

<xsl:for-each select="key('rootkey','second')"> 
    <xsl:variable name="root" select="generate-id()" /> 
    <xsl:for-each select="item/something"> 
     <xsl:sort order="ascending" select="." data-type="text"/> 
     <xsl:if test="generate-id() = generate-id(key('item-by-value', .)[generate-id(ancestor::root)=$root][1])"> 
      <xsl:value-of select="."/> 
     </xsl:if> 
    </xsl:for-each> 
</xsl:for-each> 
+0

耶已经关闭了相当一段时间哈哈,即使与[1]我仍然得到相同的结果 – Nathan 2010-04-30 00:45:42

+0

有人试图帮助时没有必要是粗鲁的。起初,我误解了问题的“独特”部分。我对代码做了一些小修改以反映想要的结果。 – Lucero 2010-04-30 09:41:59

2

这是你必须使用一个复合键的情况。

该转化

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text"/> 

<xsl:key name="kSomethingByNameAndVal" match="something" 
    use="concat(../../name, '+', .)"/> 

<xsl:template match="/"> 
    <xsl:for-each select="*/*"> 
    <xsl:for-each select= 
     "item/something 
      [generate-id() 
      = 
       generate-id(key('kSomethingByNameAndVal', 
           concat(../../name, '+', .) 
          ) 
         ) 
      ] 
     "> 

     <xsl:value-of select="."/> 
    </xsl:for-each> 
    <xsl:text>&#xA;</xsl:text> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

当所提供的XML文档施加正确地产生希望的结果

ABCD

EBFAD