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

标签 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>

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

谢谢!

最佳答案

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

<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)"/>

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

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

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

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

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

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

<xsl:template match="peptide"/>

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

关于xslt - javascript XSLT 节点,选择组中的第一个(类似合并),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8466734/

相关文章:

java - 不打印堆栈中输入的第一个节点(toString)

html - 从 .HTML 文件链接到 .XSL 文件

javascript - 按嵌套的相关数组元素对数组进行分组

objective-c - NSFetchRequest propertiesToGroupBy 可以不区分大小写吗?

Python用多个字典组织数据

javascript - NodeList 更改不影响长度

neo4j - Neo4j 中的气泡大小

XSLT 查找和替换回车

xslt - 在 TeamCity 上运行 XSLT 转换

xml - XQuery中是否有一个xsl:for-each-group等效项?