我最近问过一个关于如何忽略多个元素的问题,并且对于使用“前面”和Muenchian方法得到了一些很好的回答。但是我想知道是否可以使用索引xml文件在多个文件中执行此操作。
INDEX.XML
<?xml-stylesheet type="text/xsl" href="merge2.xsl"?>
<list>
<entry name="File1.xml" />
<entry name="File2.xml" />
</list>
XML文件示例
<Main>
<Records>
<Record>
<Description>A</Description>
</Record>
<Record>
<Description>A</Description>
</Record>
<Record>
<Description>B</Description>
</Record>
<Record>
<Description>C</Description>
</Record>
</Records>
<Records>
<Record>
<Description>B</Description>
</Record>
<Record>
<Description>A</Description>
</Record>
<Record>
<Description>C</Description>
</Record>
<Record>
<Description>C</Description>
</Record>
</Records>
</Main>
Merge2.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" indent="yes" />
<xsl:key name="Record-by-Description" match="Record" use="Description"/>
<xsl:template match="@* | node()">
<xsl:apply-templates select="@* | node()"/>
</xsl:template>
<xsl:template match="Main">
<table>
<tr>
<th>Type</th>
<th>Count</th>
</tr>
<xsl:apply-templates select="Records"/>
</table>
</xsl:template>
<xsl:template match="Records">
<xsl:apply-templates select="Record[generate-id() = generate-id(key('Record-by-Description', Description)[1])]" mode="group"/>
</xsl:template>
<xsl:template match="Record" mode="group">
<tr>
<td>
<xsl:value-of select="Description"/>
</td>
<td>
<xsl:value-of select="count(key('Record-by-Description', Description))"/>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
这在一个文件上工作正常,并为我提供了生成一个表所需的结果,只显示了唯一的项目并添加了计数。但是,在浏览多个文件的index.xml时,我无法生成所需的结果。
我尝试使用一个针对index.xml的单独模板,并将'Main'模板应用于不同的XML文件,并尝试使用for-each循环遍历不同的文件。
在介绍Muenchian方法之前,我使用for-each和'previous'来检查重复的节点,但是'previous'似乎只搜索当前文档并且无法找到有关使用它的信息多文件。
这些方法中的任何一种都能够在多个文档中搜索重复的元素文本吗?
非常感谢您的帮助。
答案 0 :(得分:3)
基本上每个文档都构建了密钥,因此基于Muenchian分组的直接密钥不允许您识别和删除多个文档中的重复项。
然而,您可以先将两个文档合并为一个,然后将Muenchian分组应用于合并文档。
如果要在一个样式表中合并和分组,则需要使用exsl:node-set
或类似内容:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="exsl">
<xsl:output method="xml" indent="yes" />
<xsl:key name="Record-by-Description" match="Record" use="Description"/>
<xsl:template match="/">
<xsl:variable name="merged-rtf">
<Main>
<xsl:copy-of select="document(list/entry/@name)/Main/Records"/>
</Main>
</xsl:variable>
<xsl:apply-templates select="exsl:node-set($merged-rtf)/Main"/>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:apply-templates select="@* | node()"/>
</xsl:template>
<xsl:template match="Main">
<table>
<tr>
<th>Type</th>
<th>Count</th>
</tr>
<xsl:apply-templates select="Records"/>
</table>
</xsl:template>
<xsl:template match="Records">
<xsl:apply-templates select="Record[generate-id() = generate-id(key('Record-by-Description', Description)[1])]" mode="group"/>
</xsl:template>
<xsl:template match="Record" mode="group">
<tr>
<td>
<xsl:value-of select="Description"/>
</td>
<td>
<xsl:value-of select="count(key('Record-by-Description', Description))"/>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
现在,您将index.xml作为主输入文档传递给样式表。
如果要在IE浏览器中进行此转换,则需要将exsl:node-set
替换为Microsoft ms:node-set
(使用正确的命名空间),或者需要使用{{3}中的方法确保exsl:node-set
函数已实现。
答案 1 :(得分:2)
如果可以的话,虽然已经用Muenchian方法回答了这个问题,但是12年来我一直在邮件列表(例如http://www.sourceware.org/ml/xsl-list/2001-10/msg00933.html)和课堂上推广基于变量的XSLT 1.0分组方法。
基于变量的分组方法允许您在一次传递中对多个文件进行分组。使用基于变量的方法进行子组也非常简单。无论您可以解决的是什么人口都可以放入变量,然后分组方法适用于该变量。
我希望下面的说明性成绩单有助于...您可以看到样式表非常紧凑,您不需要两次通过而且您不需要使用任何扩展名。
数据:
t:\ftemp>type multi.xml
<?xml-stylesheet type="text/xsl" href="merge2.xsl"?>
<list>
<entry name="File1.xml" />
<entry name="File2.xml" />
</list>
t:\ftemp>type File1.xml
<Main>
<Records>
<Record>
<Description>A</Description>
</Record>
<Record>
<Description>A</Description>
</Record>
<Record>
<Description>B</Description>
</Record>
<Record>
<Description>C</Description>
</Record>
</Records>
<Records>
<Record>
<Description>B</Description>
</Record>
<Record>
<Description>A</Description>
</Record>
<Record>
<Description>C</Description>
</Record>
<Record>
<Description>C</Description>
</Record>
</Records>
</Main>
结果:
t:\ftemp>call xslt multi.xml multi.xsl
<?xml version="1.0" encoding="utf-8"?>
<table>
<tr>
<th>Type</th>
<th>Count</th>
</tr>
<tr>
<td>A</td>
<td>6</td>
</tr>
<tr>
<td>B</td>
<td>4</td>
</tr>
<tr>
<td>C</td>
<td>6</td>
</tr>
</table>
样式表:
t:\ftemp>type multi.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" indent="yes" />
<xsl:template match="list">
<table>
<tr>
<th>Type</th>
<th>Count</th>
</tr>
<xsl:variable name="records"
select="document(entry/@name)/Main/Records/Record"/>
<xsl:for-each select="$records">
<xsl:if test="
generate-id(.)=
generate-id($records[Description=current()/Description][1])">
<tr>
<td>
<xsl:value-of select="Description"/>
</td>
<td>
<xsl:value-of
select="count($records[Description=current()/Description])"/>
</td>
</tr>
</xsl:if>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>