2

我最近问了一个关于如何忽略多个元素的问题,并在使用“前置”和 Muenchian 方法方面得到了一些很好的回应。但是我想知道是否可以使用索引 xml 文件跨多个文件执行此操作。

索引.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>

合并2.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 的单独模板并将“主”模板应用于不同的 XML 文件,还尝试使用 for-each 循环浏览不同的文件。

在被介绍给 Muenchian 方法之前,我使用带有“preceding”的 for-each 来检查重复节点,但是“preceding”似乎只在当前文档中搜索,并且无法找到有关在多个文档中使用它的信息。

使用这些方法中的任何一种都可以在多个文档中搜索重复的元素文本吗?

非常感谢您的帮助。

4

2 回答 2

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-setMicrosoft 的ms:node-set(使用适当的命名空间),或者您需要使用http://dpcarlisle.blogspot.de/2007/05/exslt-node中的方法-set-function.html以确保exsl:node-set实现该功能。

于 2013-09-23T09:05:00.570 回答
2

如果可以的话,尽管已经用 Muenchian 方法回答了这个问题,但 12 年来,我一直在邮件列表(例如http://www.sourceware.org/ml/xsl- list/2001-10/msg00933.html ) 和教室里。

基于变量的分组方法允许您一次对多个文件进行分组。使用基于变量的方法进行子组也非常简单。无论您可以解决什么人口,都可以放入一个变量中,然后分组方法对该变量起作用。

我希望下面的说明性文字记录有所帮助……您可以看到样式表非常紧凑,您不需要两次通过,也不需要使用任何扩展。

数据:

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>
于 2013-09-23T12:09:31.193 回答