xslt动态/条件apply-template在变量的作用?

时间:2011-12-18 12:16:53

标签: xslt dynamic conditional apply-templates

我希望根据用户的需要显示两种不同的XSLT转换。整个XSL文件是相同的,除了一行。

这一行应该是

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

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

我的第一个想法是创建两个不同的.xsl文件,并将它们(javascript)应用于变量值。

var xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xslDoc);
xhtml = xsltProcessor.transformToFragment(xmlDoc,document);

但是,它只是一行,我只想维护一个文件。我想做这样的事情

<xsl:param name="variable"/>
<xsl:choose>
<xsl:when test="$variable = 0">
<xsl:template match="/data/peptides/peptide[generate-id()=generate-id(key('byAccSeq', concat(protein_accessions/accession, '|', sequence))[1])]">
...
</xsl:template>
</xsl:when>
<xsl:otherwise>
<xsl:template match="/data/peptides/peptide">
...
</xsl:template>
</xsl:otherwise>
</xsl:choose>

但它不起作用。

尝试使用xsl:apply-templates中的“mode”功能,此代码既不起作用

<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="/data/peptides/peptide" use="concat(accession, '|', sequence)"/>

<xsl:param name="analysis" select="1"/>

<xsl:template match="/">
<root><name><xsl:value-of select="$analysis"/></name><xsl:apply-templates select="/data/proteins/protein"/></root>
</xsl:template>

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

<xsl:choose>
<xsl:when test="$analysis=1">
<xsl:apply-templates select="/data/peptides/peptide" mode="one"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="/data/peptides/peptide[accession=current()/accession]" mode="two"/>
</xsl:otherwise>
</xsl:choose>

<xsl:template match="/data/peptides/peptide" mode="one">
<xsl:copy-of select="."/>
</xsl:template>

<xsl:template match="/data/peptides/peptide[generate-id()=
           generate-id(key('byAccSeq', concat(accession, '|', sequence))[1])]" mode="two">
<xsl:copy-of select="."/>
</xsl:template>

</xsl:stylesheet>

- &GT; http://www.xsltcake.com/slices/sgWUFu/2

  • 此代码不正确,因为xsl:choose不能是xsl:stylesheet的子代

求助(下面改进),这是制作我想要的代码

<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="/data/peptides/peptide" use="concat(accession, '|', sequence)"/>
    <xsl:param name="analysis" select="1"/>
    <xsl:template match="/">
        <root>
            <name>
                <xsl:value-of select="$analysis"/>
            </name>
            <xsl:apply-templates select="/data/proteins/protein"/>
        </root>
    </xsl:template>
    <xsl:template match="/data/proteins/protein">
        <xsl:choose>
            <xsl:when test="$analysis=1">
                <xsl:apply-templates select="/data/peptides/peptide[accession=current()/accession]" mode="one"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="/data/peptides/peptide[accession=current()/accession]" mode="two"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    <xsl:template match="/data/peptides/peptide" mode="one">
        <xsl:copy-of select="."/>
    </xsl:template>

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

    <xsl:template match="/data/peptides/peptide[generate-id()=
    generate-id(key('byAccSeq', concat(accession, '|', sequence)))]" mode="two">
    <xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>

改进:使用更少的重复代码更容易阅读最终代码 here

<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:param name="analysis" select="0"/>
    <xsl:key name="byAcc"    match="/data/peptides/peptide" use="accession" />
    <xsl:key name="byAccSeq" match="/data/peptides/peptide" use="concat(accession, '|', sequence)"/>
    <xsl:template match="/">
        <root>
            <name>
                <xsl:value-of select="$analysis"/>
            </name>
            <xsl:apply-templates select="/data/proteins/protein" />
        </root>
    </xsl:template>
    <xsl:template match="/data/proteins/protein">
        <xsl:choose>
            <xsl:when test="$analysis=1">
                <xsl:apply-templates select="key('byAcc',accession)" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="key('byAcc',accession)[
                generate-id()
                =
                generate-id(key('byAccSeq', concat(accession, '|', sequence)))]" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    <xsl:template match="/data/peptides/peptide">
        <xsl:copy-of select="."/>
    </xsl:template>
</xsl:stylesheet>

我保留了apply-template调用,因为我需要它,但没有它们(如在原始代码中,请参阅注释)甚至更简单。

再次感谢,不仅是为了回答,还为了教授XSLT:)

2 个答案:

答案 0 :(得分:1)

/data/peptides/peptide[
  generate-id()
  =
  generate-id(
    key('byAccSeq', concat(protein_accessions/accession, '|', sequence))[1]
  )
]

/data/peptides/peptide[
  generate-id()
  =
  generate-id(
    key('byAccSeq', concat(protein_accessions/accession, '|', sequence))
  )
]

是等价的。 generate-id()始终返回已传递给它的节点集中第一个节点的ID。

因此,无论您使用generate-id(some-node-set)还是generate-id(some-node-set[1]),都没有任何区别。您可以使用其中一个XSLT文件。

答案 1 :(得分:1)

<xsl:template>更改为<xsl:apply-templates>

<xsl:apply-templates select="/data/peptides/peptide[generate-id()=generate-id(key('byAccSeq', concat(protein_accessions/accession, '|', sequence))[1])]" mode="type1" />

<xsl:apply-templates select="/data/peptides/peptide[generate-id()=generate-id(key('byAccSeq', concat(protein_accessions/accession, '|', sequence)))]" mode="type2" />

之后,相应地为这两者写一个<xsl:template>

以更短的方式修改您的解决方案:

<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="/data/peptides/peptide" use="concat(accession, '|', sequence)"/>
    <xsl:param name="analysis" select="2"/>
    <xsl:template match="/">
        <root>
            <name>
                <xsl:value-of select="$analysis"/>
            </name>
            <xsl:apply-templates select="data[peptides/peptide/accession=proteins/protein/accession]/peptides" />
        </root>
    </xsl:template>
    <xsl:template match="peptides">
        <xsl:choose>
            <xsl:when test="$analysis=1">
                <xsl:copy-of select="peptide"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:for-each select="peptide[generate-id()=generate-id(key('byAccSeq', concat(accession, '|', sequence)))]">
                    <xsl:copy-of select="."/>
                </xsl:for-each>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

我已根据您的输入XML&amp;测试了我的代码输出。现在我可以复制它。

在我的代码中,我仍然可以减少一些代码行

<xsl:for-each>替换为以下行: -

<xsl:copy-of select="peptide[generate-id()=generate-id(key('byAccSeq', concat(accession, '|', sequence)))]"/>

检查出来..