XSLT сортировка групп узлов, ранее выбранных с помощью ключа - PullRequest
0 голосов
/ 18 декабря 2011

У меня есть XML-файл с группой protein узлов, каждый с номером accession. И группа из peptides каждая с параметрами accession, sequence, RT и score.

И у меня есть XSLT-файл, в котором для каждого белка называются все пептидные узлы, имеющие одинаковое accession число белка.

Затем, в зависимости от значения переменной, здесь <xsl:param name="analysis" select="0"/>, файл XSLT вызывает все пептиды с одинаковым номером accession или все пептиды с одинаковым номером accession, но отбрасывает все из них. совпадающие значения sequence.

Вот код, который делает то, что я сказал (изменяя значение переменной с 0 на 1, можно увидеть 2 ситуации, которые я описал)

ссылка

Я также вставляю код в конец поста

Теперь мне нужно отсортировать и выбрать пептидные узлы, которые имеют максимальную оценку.

Итак, в случае, когда XSLT-файл вызывает все пептиды с одинаковым номером accession, мне нужно, чтобы они были отсортированы в зависимости от значений оценки.

И, в случае, когда код вызывает все пептиды с одинаковым номером accession, но выбирая только один пептид из тех, которые также имеют одинаковые последовательности, мне нужно, чтобы этот пептид был с максимальным счетом, не только первое, что входит в XML-файл.

Я пытался использовать функцию «сортировки» в этом коде ссылка , но если вы посмотрите на это, вы увидите, что вывод XML упорядочивает все пептиды, теряя предыдущие пре- группировка выполняется с помощью оператора key.

XML-код

<data>
    <proteins>
        <protein>
            <accession>111</accession>
        </protein>
    </proteins>
    <peptides>
        <peptide>
            <accession>111</accession>
            <sequence>AAA</sequence>
            <RT>13</RT>
            <score>4000</score>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>AAA</sequence>
            <RT>14</RT>
            <score>6000</score>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>AAA</sequence>
            <RT>15</RT>
            <score>5000</score>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>BBB</sequence>
            <RT>23</RT>
            <score>5000</score>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>BBB</sequence>
            <RT>24</RT>
            <score>1000</score>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>BBB</sequence>
            <RT>25</RT>
            <score>8000</score>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>BBB</sequence>
            <RT>26</RT>
            <score>5000</score>
        </peptide>
    </peptides>
</data>

XSLT код

<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:apply-templates>
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="key('byAcc',accession)[
                generate-id()
                =
                generate-id(key('byAccSeq', concat(accession, '|', sequence)))]">
            </xsl:apply-templates>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
<xsl:template match="/data/peptides/peptide">
    <xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>

И вывод XML, который мне нужен, по причинам простоты, когда выбран только один пептид <xsl:param name="analysis" select="0"/>

<root>
    <name>0</name>
    <peptide>
        <accession>111</accession>
        <sequence>AAA</sequence>
        <RT>14</RT>
        <score>6000</score>
    </peptide>
    <peptide>
        <accession>111</accession>
        <sequence>BBB</sequence>
        <RT>25</RT>
        <score>8000</score>
    </peptide>
</root>

Это из двух пептидных узлов, имеющих общие значения accession и sequence, с максимальным значением score

Спасибо

----------------------------------------------- ----------------------------

РЕДАКТИРОВАТЬ: Попытка прояснить вопрос

Самый простой код, который я могу придумать, будет:

У меня есть этот код XML

<data>
    <peptides>
        <peptide>
            <accession>111</accession>
            <sequence>AAA</sequence>
            <score>4000</score>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>AAA</sequence>
            <score>6000</score>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>AAA</sequence>
            <score>5000</score>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>BBB</sequence>
            <score>5000</score>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>BBB</sequence>
            <score>1000</score>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>BBB</sequence>
            <score>8000</score>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>BBB</sequence>
            <score>5000</score>
        </peptide>
        <peptide>
            <accession>222</accession>
            <sequence>CCC</sequence>
            <score>5000</score>
        </peptide>
        <peptide>
            <accession>222</accession>
            <sequence>CCC</sequence>
            <score>9000</score>
        </peptide>
        <peptide>
            <accession>222</accession>
            <sequence>CCC</sequence>
            <score>2000</score>
        </peptide>
  </peptides>
</data>

, не предполагая, что способ сортировки согласован, так что этот XML может иметь узлы в любом положении.

Затем я хочу сгруппировать узлы сначала по присоединению, затем внутри этих узлов, сгруппировать их по последовательности, а затем внутри этих узлов, чтобы отсортировать их по баллам.

Таким образом, выходной XML будет таким

<data>
    <peptides>
        <peptide>
            <accession>111</accession>
            <sequence>AAA</sequence>
            <score>6000</score>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>AAA</sequence>
            <score>5000</score>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>AAA</sequence>
            <score>4000</score>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>BBB</sequence>
            <score>8000</score>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>BBB</sequence>
            <score>5000</score>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>BBB</sequence>
            <score>5000</score>
        </peptide>
        <peptide>
            <accession>111</accession>
            <sequence>BBB</sequence>
            <score>1000</score>
        </peptide>
        <peptide>
            <accession>222</accession>
            <sequence>CCC</sequence>
            <score>9000</score>
        </peptide>
        <peptide>
            <accession>222</accession>
            <sequence>CCC</sequence>
            <score>5000</score>
        </peptide>
        <peptide>
            <accession>222</accession>
            <sequence>CCC</sequence>
            <score>2000</score>
        </peptide>
  </peptides>
</data>

РЕШЕНИЕ к этому последнему коду, из любезно предоставленного ответа:

<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="byAcc"    match="/data/peptides/peptide" use="accession" />
    <xsl:key name="byAccSeq" match="/data/peptides/peptide" use="concat(accession, '|', sequence)"/>
    <xsl:template match="/">
        <root>
            <xsl:apply-templates select="/data/proteins/protein">
            </xsl:apply-templates>
        </root>
    </xsl:template>
    <xsl:template match="/data/proteins/protein">
        <xsl:apply-templates select="key('byAcc',accession)">
            <xsl:sort select="sequence" data-type="text"/>
            <xsl:sort select="score" data-type="number"/>
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="/data/peptides/peptide">
        <xsl:copy-of select="."/>
    </xsl:template>
</xsl:stylesheet>

отметьте здесь

1 Ответ

1 голос
/ 18 декабря 2011

Непонятно, какая именно обработка требуется, но здесь я предоставляю две различные комбинации группировки и сортировки (я также предполагаю, что требуется XSLT 1.0):

Давайте получимследующий очень простой XML-документ:

<nums>
 <num>5</num>
 <num>1</num>
 <num>2</num>
 <num>2</num>
 <num>9</num>
 <num>1</num>
 <num>5</num>
 <num>2</num>
 <num>9</num>
 <num>8</num>
</nums>

Если мы хотим устранить дубликаты, мы можем начать с этого преобразования :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:key name="kNumByVal" match="num" use="."/>

 <xsl:template match="/*">
  <nums>
    <xsl:copy-of select=
    "num
      [generate-id(key('kNumByVal', .)[1])
      =
       generate-id()
      ]"/>
  </nums>
 </xsl:template>
</xsl:stylesheet>

результат :

<nums>
   <num>5</num>
   <num>1</num>
   <num>2</num>
   <num>9</num>
   <num>8</num>
</nums>

Теперь, если мы хотим, чтобы в результате элементы num были отсортированы по значению , есть два разных решения:

  1. Сортировка исходного XML-документа и последующая группировка:

...

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:key name="kNumByVal" match="num" use="."/>

 <xsl:template match="/*">

  <xsl:variable name="vrtfSorted">
   <xsl:for-each select="num">
    <xsl:sort data-type="number"/>
    <xsl:copy-of select="."/>
   </xsl:for-each>
  </xsl:variable>

  <xsl:variable name="vSorted" select=
       "ext:node-set($vrtfSorted)/*"/>

  <nums>
   <xsl:for-each select=
    "$vSorted
      [generate-id(key('kNumByVal', .)[1])
      =
       generate-id()
      ]
     ">
    <xsl:sort data-type="number"/>
    <xsl:copy-of select="."/>
   </xsl:for-each>
  </nums>
 </xsl:template>
</xsl:stylesheet>

получен правильный результат :

<nums>
   <num>1</num>
   <num>2</num>
   <num>5</num>
   <num>8</num>
   <num>9</num>
</nums>

.2.Выполните группировку и затем отсортируйте результат:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:key name="kNumByVal" match="num" use="."/>

 <xsl:template match="/*">

    <xsl:variable name="vDistinct" select=
    "num
      [generate-id(key('kNumByVal', .)[1])
      =
       generate-id()
      ]"/>

  <nums>
   <xsl:for-each select="$vDistinct">
    <xsl:sort data-type="number"/>
    <xsl:copy-of select="."/>
   </xsl:for-each>
  </nums>
 </xsl:template>
</xsl:stylesheet>

, снова будет получен правильный результат :

<nums>
   <num>1</num>
   <num>2</num>
   <num>5</num>
   <num>8</num>
   <num>9</num>
</nums>

Обновление : после уточненийв комментарии OP, вот новый пример:

<nums>
  <num seq="1">01</num>
  <num seq="2">01</num>
  <num seq="1">01</num>
  <num seq="3">01</num>
  <num seq="2">01</num>
  <num seq="4">01</num>
  <num seq="1">02</num>
  <num seq="2">3</num>
  <num seq="3">04</num>
  <num seq="3">01</num>
  <num seq="4">02</num>
  <num seq="1">01</num>
</nums>

Требуется для группировки по @seq и по строковому значению элемента и сортировки по обоим@seq и строковое значение:

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

 <xsl:key name="kBySeqVal" match="num"
  use="concat(@seq, '+', .)"/>

 <xsl:key name="kByValSeq" match="num"
  use="concat(., '+', @seq.)"/>

 <xsl:template match="/">
  <xsl:apply-templates select=
   "/*/*
     [generate-id()
     =
      generate-id(key('kBySeqVal',
                      concat(@seq, '+', .)
                      )
                       [1]
                  )
     ]
   ">
    <xsl:sort select="@seq" data-type="number"/>
    <xsl:sort select="." data-type="number"/>
   </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="num">
  <xsl:copy-of select="."/>
 </xsl:template>
</xsl:stylesheet>

, а результат группируется и сортируется точно так, как требуется :

<num seq="1">01</num>
<num seq="1">02</num>
<num seq="2">01</num>
<num seq="2">3</num>
<num seq="3">01</num>
<num seq="3">04</num>
<num seq="4">01</num>
<num seq="4">02</num>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...