我在对文档中的一组节点进行分组并根据一组包含的值获取唯一列表时遇到了一个非常奇怪的问题。
给定以下 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>
我正在尝试生成一个以竖线分隔的字符串,其中包含“Friend”标签中的所有名称。这是我当前使用的样式表:
<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>
我遇到的问题是输出忽略了最后一个 friend 。结果如下:
Billy Bob Smith|
有趣的是,如果我删除最后一个“Gift”元素,它会产生我正在寻找的输出:
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();
}
}
}
欢迎您提供任何帮助。
最佳答案
您使用 Saxon 6.5 测试的转换运行良好,并且产生了想要的结果:
Billy Bob Smith|Mary Jo Smith
这可能是与 java XSLT api 相关的问题。该 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>
关于java - 使用 Muenchian 分组方法的 XSLT 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6363649/