2011-12-18 1 views
0

Я хочу показать два разных преобразования XSLT в зависимости от того, чего хочет пользователь. Весь XSL-файл является одним и тем же, за исключением одной строки.xslt динамический/условный шаблон apply в функции переменной?

Эта линия должна быть как

<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: не применять-шаблоны, этот код ни работает

<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: выбор не может быть ребенок XSL: таблица стилей

РЕШИТЬ (улучшенный ниже), это код, который делает то, что я хотел

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

я держу применить-шаблон вызовы, потому что мне это нужно, но без них (как и в оригинале код, см. комментарии) еще проще.

Еще раз спасибо, не только для ответа, но для обучения XSLT :)

+0

Посмотрите на улучшенной версии вашего решения: http://www.xsltcake.com/slices/sgWUFu/5 – Tomalak

ответ

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() всегда возвращает идентификатор первого узла в наборе узлов, который был передан ему.

Поэтому не имеет значения, используете ли вы generate-id(some-node-set) или generate-id(some-node-set[1]). Вы можете использовать один из XSLT-файлов.

+0

Вы правы, но в прошлом мне удалось получить не первый, а все узлы, так что я получил разницу ([ссылка ] (http://stackoverflow.com/questions/8466734/javascript-xslt-nodes-selecting-the -first-of-a-group-merge-like/8468098 # 8468098)), то теперь мне нужно восстановить это выражение – Gerard

+0

Решено (и отредактировано), спасибо! – Gerard

+0

@ Герард: Я не уверен, что вы там делаете. Ваши шаблоны «режим 1» и «режим 2» выполняют ту же самую вещь (то есть «'). Какой смысл иметь два одинаковых шаблона? Кроме того, '' не может быть дочерним элементом '', поэтому, с моей точки зрения, этот код даже не синтаксически корректен. – Tomalak

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

Проверьте это ..

+0

Я стараюсь, как вы предлагаете, без успеха. [Код] (http://www.xsltcake.com/slices/sgWUFu/2) – Gerard

+0

@Gerard: У меня есть обновленный ответ с правильным кодом XSLT (на основе вашего кода). Теперь я могу реплицировать тот же результат, что и ваш входной XML. Проверьте и дайте мне знать. –

+0

Большое спасибо. Поскольку мне нужно сохранить вызовы с применением шаблона, я думаю, что для каждого решения не будет работать. Вместо этого использование двух групп узлов с «ключом» и вызов используемых ими шаблонов - это самый простой способ сделать это. – Gerard