检索一个元素并按另一个元素过滤

时间:2009-10-23 13:31:03

标签: xslt xpath sorting distinct

尝试过并且未能从此处修改XSL:Distinct elements and grouping

我在这里发帖询问是否有人可以请求帮助。我基本上得到了相同的数据结构(我的实际上是产品的RSS源),如上所述,但我想以排序顺序唯一地列出Description元素,其中File元素包含特定值。

我相信文件选择的XPath将是:

*/File[text()='file1']
例如,

仅包含包含文本“file1”的File元素。

我无法弄清楚如何获取:“所有不同的Description元素已排序,其中的文件同级值为'file1'”。

非常非常感谢任何和所有的帮助!

谢谢,

1 个答案:

答案 0 :(得分:1)

XSLT 1.0:

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

  <!-- index Description elements by their text value -->
  <xsl:key name="kDescription" match="Description" use="text()" />

  <xsl:template match="/">
    <output>
      <!-- process all Description elements... -->
      <xsl:apply-templates select="Problems/Problem/Description">
        <!-- ...sorted by their own text value, ascending -->
        <xsl:sort select="text()" />
        <!-- pass in the File value that we want to filter for -->
        <xsl:with-param name="file" select="'file1'" />
      </xsl:apply-templates>
    </output>
  </xsl:template>

  <xsl:template match="Description">
    <xsl:param name="file" select="''" />
    <!-- 
      check if the current Description node is the first in its
      respective group, that has a File value we care for
    -->
    <xsl:if test="
      $file != ''
      and
      generate-id()
      =
      generate-id(key('kDescription', .)[../File = $file][1])
    ">
      <!-- for the sake of simplicity, just make a copy here -->
      <xsl:copy-of select="." />
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

使用此输入:

<Problems>
  <Problem>
    <File>file1</File>
    <Description>desc1</Description>
  </Problem>
  <Problem>
    <File>file1</File>
    <Description>desc2</Description>
  </Problem>
  <Problem>
    <File>file2</File>
    <Description>desc3</Description>
  </Problem>
  <Problem>
    <File>file2</File>
    <Description>desc1</Description>
  </Problem>
  <Problem>
    <File>file1</File>
    <Description>desc2</Description>
  </Problem>
</Problems>    

我明白了:

<output>
  <Description>desc1</Description>
  <Description>desc2</Description>
</output>

对繁重工作的样式表部分的简要说明:

$file != ''
and
generate-id()
=
generate-id(key('kDescription', .)[../File = $file][1])

第一部分是显而易见的 - 它只是确保传入$file过滤字符串。

第二部分是简单的Muenchian分组,有点扭曲。它比较两个节点的ID,即当前的generate-id()}和kDescription组中的一个,按$file值过滤。

kDescription根据文本值索引<Description>元素,这意味着调用<File>将返回具有相同文本但附带key()不同的节点。我们需要将它们过滤掉。

如果当前节点等于具有正确<File>值的组的第一个节点,则测试成功并打印一些内容,否则不会发生任何事情。