0

ユーザーが望む機能に応じて、2 つの異なる XSLT 変換を表示したいと考えています。XSL ファイル全体は、1 行を除いて同じです。

この行はそのままである必要があります

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

またはそのまま

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

私の最初のアイデアは、2 つの異なる .xsl ファイルを作成し、それら (javascript) を変数値の関数として適用することでした。

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

ただし、それは単なる行であり、1 つのファイルのみを維持したいと考えています。私はこのようなことをしたいと思います

<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 の機能「モード」を試してみると、このコードはどちらも機能しません

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

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

改善: 最終的なコードは、重複するコードが大幅に減り、読みやすくなってい ます。

<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を教えてくれてありがとう:)

4

2 に答える 2

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 ファイルを使用できます。

于 2011-12-18T12:23:25.490 に答える
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と出力に従ってコードをテストしました。これで、同じものを複製できます。

私のコードでは、さらにコード行を減らすことができます

以下の行に置き換え<xsl:for-each>ます:-

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

見てみな..

于 2011-12-18T12:27:57.663 に答える