javascript XSLT节点,选择组中的第一个(类似合并)

时间:2011-12-11 19:22:45

标签: xslt grouping nodes

在阅读了这里的一些合并帖后,我的问题看起来更简单了,我无法找到答案。所以我发布了一个新问题。

原始xml

<data>

<proteins>
<protein>
<accession>111</accession>
</protein>
</proteins>

<peptides>
<peptide>
<accession>111</accession>
<sequence>AAA</sequence>
</peptide>
<peptide>
<accession>111</accession>
<sequence>AAA</sequence>
</peptide>
<peptide>
<accession>111</accession>
<sequence>AAA</sequence>
</peptide>
<peptide>
<accession>111</accession>
<sequence>BBB</sequence>
</peptide>
<peptide>
<accession>111</accession>
<sequence>BBB</sequence>
</peptide>
<peptide>
<accession>111</accession>
<sequence>BBB</sequence>
</peptide>
<peptide>
<accession>111</accession>
<sequence>BBB</sequence>
</peptide>
</peptides>

</data>

xslt,用作浏览器解释的.xsl页面

<xsl:template match="/">
<xsl:apply-templates select="/data/proteins/protein" />
</xsl:template>

<xsl:template match="/data/proteins/protein">
<xsl:apply-templates select="/data/peptides/peptide[accession = current()/accession]" >
</xsl:template>

<xsl:template match="/data/peptides/peptide">
...
</xsl:template>

我得到的输出(概念上,因为这是对更大代码的简化)

<peptide>
<accession>111</accession>
<sequence>AAA</sequence>
</peptide>
<peptide>
<accession>111</accession>
<sequence>AAA</sequence>
</peptide>
<peptide>
<accession>111</accession>
<sequence>AAA</sequence>
</peptide>
<peptide>
<accession>111</accession>
<sequence>BBB</sequence>
</peptide>
<peptide>
<accession>111</accession>
<sequence>BBB</sequence>
</peptide>
<peptide>
<accession>111</accession>
<sequence>BBB</sequence>
</peptide>
<peptide>
<accession>111</accession>
<sequence>BBB</sequence>
</peptide>

和我想要的输出,即每个序列只有一个条目,以避免减少

<peptide>
<accession>111</accession>
<sequence>AAA</sequence>
</peptide>
<peptide>
<accession>111</accession>
<sequence>BBB</sequence>
</peptide>

我很高兴只拥有共享相同序列的第一个节点(因此不合并它们)。 任何帮助都非常欢迎:)

谢谢!

2 个答案:

答案 0 :(得分:2)

缺少样式表的方法是识别一组相同项目中的第一个。以下样式表使用xsl:key通过peptideaccession值的组合对sequence元素进行分组:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:key name="byAccSeq" match="peptide" 
                             use="concat(accession, '|', sequence)"/>
    <xsl:template match="/">
        <root><xsl:apply-templates select="/*/proteins/protein"/></root>
    </xsl:template>
    <xsl:template match="protein">
        <xsl:apply-templates
            select="../../peptides/peptide[accession=current()/accession]"/>
    </xsl:template>
    <xsl:template match="peptide[generate-id()=
             generate-id(key('byAccSeq', concat(accession, '|', sequence))[1])]">
        <xsl:copy-of select="."/>
    </xsl:template>
    <xsl:template match="peptide"/>
</xsl:stylesheet>

输出:

<root>
    <peptide>
        <accession>111</accession>
        <sequence>AAA</sequence>
    </peptide>
    <peptide>
        <accession>111</accession>
        <sequence>BBB</sequence>
    </peptide>
</root>

说明:以下一行:

<xsl:key name="byAccSeq" match="peptide" 
                         use="concat(., accession, sequence)"/>

...使用值等于peptide的键对concat(., accession, sequence)个元素进行分组。稍后可以通过复制某些peptide元素的键来检索元素:

key('byAccSeq', concat(/path/to/peptide, accession, sequence))

要匹配为某个键返回的节点列表中的第一个元素,我们使用以下模板/模式:

<xsl:template match="peptide[generate-id()=
               generate-id(key('byAccSeq', concat(., accession, sequence))[1])]">

generate-id函数为文档中的每个节点返回唯一标识符。我们要求任何peptide元素,其唯一ID等于某个键列表中第一个节点的唯一ID。

然后我们忽略所有其他peptide元素 - 那些不是某些键的第一个元素 - 使用以下模板:

<xsl:template match="peptide"/>

这种分组技术称为Muenchian方法。进一步阅读:

答案 1 :(得分:1)

备用Muenchian grouping (只有一个模板和一条指令):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kPepByAccAndSeq" match="peptide"
  use="concat(accession, '+', sequence)"/>

 <xsl:template match="/">
   <xsl:copy-of select=
    "/*/peptides
          /peptide
              [generate-id()
              =
               generate-id(key('kPepByAccAndSeq',
                               concat(accession, '+', sequence)
                              )[1]
                          )
              ]
    "/>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于提供的XML文档

<data>
    <proteins>
        <protein>
            <accession>111</accession>
        </protein>
    </proteins>
    <peptides>
        <peptide>
            <accession>111</accession>
            <sequence>AAA</sequence>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>AAA</sequence>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>AAA</sequence>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>BBB</sequence>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>BBB</sequence>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>BBB</sequence>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>BBB</sequence>
        </peptide>
    </peptides>
</data>

产生了想要的正确结果

<peptide>
   <accession>111</accession>
   <sequence>AAA</sequence>
</peptide>
<peptide>
   <accession>111</accession>
   <sequence>BBB</sequence>
</peptide>

解释:Muenchian分组,其中键值是两个元素值的组合。