2011-06-15 105 views
1

我在分组文档中的一组节点并基于一组包含的值获取唯一列表时遇到了一个非常奇怪的问题。使用Muenchian分组方法的XSLT问题

给出下面的XML:

<Person> 
    <FirstName>John</FirstName> 
    <MiddleName>Q</MiddleName> 
    <LastName>Person</LastName> 
    <Gift> 
     <Thing>Moon</Thing> 
     <Friend> 
      <FirstName>Billy</FirstName> 
      <MiddleName>Bob</MiddleName> 
      <LastName>Smith</LastName> 
     </Friend> 
     <Friend> 
      <FirstName>Mary</FirstName> 
      <MiddleName>Jo</MiddleName> 
      <LastName>Smith</LastName> 
     </Friend> 
    </Gift> 
    <Gift> 
     <Thing>Pencil</Thing> 
    </Gift> 
</Person> 

我想产生一个管道分隔字符串中的所有“好友”标签的名称。这里是我正在使用的当前样式表:

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

    <xsl:key name="Friends" match="Friend" use="concat(FirstName, MiddleName, LastName)"/> 

    <xsl:template match="/Person"> 
    <xsl:for-each select="Gift/Friend[count(. | key('Friends', concat(FirstName, MiddleName, LastName))[1]) = 1]"> 
     <xsl:apply-templates select="."/> 
     <xsl:if test="position()!=last()"> 
     <xsl:text>|</xsl:text> 
     </xsl:if> 
    </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="Friend"> 
    <xsl:variable name="name"> 
     <xsl:value-of select="FirstName"/><xsl:text> </xsl:text> 
     <xsl:value-of select="MiddleName"/><xsl:text> </xsl:text> 
     <xsl:value-of select="LastName"/><xsl:text> </xsl:text> 
    </xsl:variable> 
    <xsl:value-of select="normalize-space($name)"/> 
    </xsl:template> 

</xsl:stylesheet> 

我遇到的问题是输出省略了最后一个朋友。下面是结果:

Billy Bob Smith| 

有趣的是,如果我删除最后一个“礼物”的元素,它产生我在寻找的输出:

Billy Bob Smith|Mary Jo Smith 

以供参考,在这里是Java用于执行转换的代码:

package testing; 

import java.io.*; 
import javax.xml.transform.*; 
import javax.xml.transform.stream.*; 

public class test 
{ 
    public static void main(String[] args) 
    { 
    try 
    {  
     StreamSource xsl = new StreamSource("xslt/person.xslt"); 
     StreamSource xml = new StreamSource("xslt/person.xml"); 
     Transformer txfm = TransformerFactory.newInstance().newTransformer(xsl); 
     if (txfm != null) 
     { 
     ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 
     txfm.transform(xml, new StreamResult(bytes)); 
     System.out.println(bytes.toString()); 
     }  

    } 
    catch (Exception e) 
    { 
     e.printStackTrace(); 
    } 
    } 
} 

您可以提供的任何帮助都将受到欢迎。

回答

0

你的变换与撒克逊6.5工作完全测试,它产生的通缉的结果:

Billy Bob Smith|Mary Jo Smith 

这可能是相关的Java API XSLT的问题。可能API不完全支持XSLT 1.0功能,例如xsl:key。您可以进行进一步测试,并尝试不使用密钥。

<xsl:template match="/Person"> 
     <xsl:for-each select="Gift/Friend[not(
      concat(FirstName,MiddleName,LastName) 
      = 
      preceding::Friend[concat(FirstName, MiddleName, LastName)] 
      )]"> 
     <xsl:apply-templates select="."/> 
     <xsl:if test="position()!=last()"> 
     <xsl:text>|</xsl:text> 
     </xsl:if> 
    </xsl:for-each> 
    </xsl:template> 
+0

好,解释它:

例如,该模板不使用任何键执行相同的任务。谢谢。 – pconrey 2011-06-15 20:52:31

+0

没有钥匙工作的版本? – 2011-06-15 20:55:00

+0

我还没试过。我需要一个快速解决方案来推出一些东西,所以我用://朋友而不是礼物/朋友。我知道基于XML,这将是可靠的。 – pconrey 2011-06-17 16:32:27