在花了几天时间尝试使用muenchian分组找到解决方案之后,我迫切需要一些帮助来找出正确的xslt代码来转换我的XML,以便它将为所有节目生成唯一的年份列表(最终导入到Solr中)。基本上我需要对节点的唯一孙子进行分组,但不知何故,SO 上的所有现有解决方案都对我不起作用。
这是我的源 XML:
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="http://localhost/default.xsl" ?>
<DIRECTORY>
<SHOWS>
<SHOW>
<TITLE>Child's play</TITLE>
<EVENTS>
<EVENT>
<YEAR>2014</YEAR>
<TITLE>Gala day</TITLE>
</EVENT>
<EVENT>
<YEAR>2014</YEAR>
<TITLE>Gala night</TITLE>
</EVENT>
<EVENT>
<YEAR>2015</YEAR>
<TITLE>Gala night</TITLE>
</EVENT>
</EVENTS>
</SHOW>
</SHOWS>
</DIRECTORY>
下面是所需的输出:
<?xml version="1.0"?>
<add>
<doc>
<field name="show_title">Child's play</field>
<field name="show_year">2014</field>
<field name="show_year">2015</field>
</doc>
</add>
这是我的 XSLT 不起作用,并且基于围绕堆栈溢出的各种答案
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>
<xsl:key name="show_key"
match="TITLE"
use="TITLE"/>
<xsl:key name="show_years_key"
match="TITLE"
use="concat(TITLE, ' ',
EVENTS/EVENT/YEAR)"/>
<xsl:template match="/">
<add>
<xsl:for-each select="/DIRECTORY/SHOWS/SHOW">
<doc>
<xsl:call-template name="show_info"/>
</doc>
</xsl:for-each>
</add>
</xsl:template>
<xsl:template name="show_info">
<field name="show_title">
<xsl:value-of select="TITLE"/>
</field>
<xsl:variable
name="show_events"
select="key('show_key', TITLE)"/>
<xsl:for-each
select="$show_events[generate-id() =
generate-id(
key('show_years_key',
concat(TITLE,
' ',
EVENTS/EVENT/YEAR))[1])]">
<field name="show_years">
<xsl:value-of select="EVENTS/EVENT/YEAR"/>
</field>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
虽然我非常感谢任何帮助以获得可行的解决方案,但我也可以使用一些指针来说明为什么我的解决方案在应该工作时不起作用。我故意将最小示例保留得稍微复杂一些,因为我怀疑我的 xslt 组织可能会使事情变得更加复杂,但整体解决方案运行良好,即使使用多个不同的模板也是如此。
分组键需要匹配您尝试分组的元素(即YEAR
元素)。 我在遵循您的call-template
逻辑时遇到了一些麻烦,我会像这样处理它:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>
<xsl:key name="show_years_key"
match="YEAR"
use="concat(ancestor::SHOW[1]/TITLE, ' ', .)"/>
<xsl:template match="/">
<add>
<xsl:apply-templates select="/DIRECTORY/SHOWS/SHOW" />
</add>
</xsl:template>
<xsl:template match="SHOW">
<doc>
<field name="show_title">
<xsl:value-of select="TITLE"/>
</field>
<!-- current() here is the SHOW element this template applies to -->
<xsl:for-each select="EVENTS/EVENT/YEAR[generate-id() = generate-id(
key('show_years_key', concat(current()/TITLE, ' ', .))[1])]">
<field name="show_years">
<xsl:value-of select="." />
</field>
</xsl:for-each>
</doc>
</xsl:template>
</xsl:stylesheet>
重要的一点是,您按包含SHOW
TITLE
对YEAR
元素进行分组,而不是按SHOW
元素包含YEAR
对元素进行分组。