Как отсортировать в XSL на основе другого списка, который был отсортирован? - PullRequest
1 голос
/ 17 октября 2019

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

<!-- <xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" />
 ^ The code above is only to show the xslt version ^ -->

<ul>
            <h1><xsl:value-of select="$first/Lexicon/Title"/></h1>
            <xsl:for-each select="$first/Lexicon/Words/Word">
              <xsl:sort select="."/>
              <li>
                <xsl:value-of select="."/>
              </li>
            </xsl:for-each>

</ul>
<ul>
            <h1><xsl:value-of select="$second/Lexicon/Title"/></h1>
            <xsl:for-each select="$second/Lexicon/Words/Word">
              <li>
                <xsl:value-of select="."/>
              </li>
            </xsl:for-each>

</ul>

Переменная $ first и $ second ссылаются на два XMLдокумент со словами. Они оба имеют одинаковую структуру.

$ first

<Lexicon>
    <Title> English </Title>
    <Author> SafeSailor </Author>
    <Words>
        <Word> Car </Word>
        <Word> Programming </Word>
        <Word> Write </Word>
        <Word> Run </Word>
        <Word> Drink </Word>
        <Word> Potato </Word>
        <Word> Rowan-berry </Word>
        <Word> Weight </Word>
        <Word> Group </Word>
        <Word> People </Word>
    </Words>
</Lexicon>

Ответы [ 2 ]

2 голосов
/ 17 октября 2019

В XSLT 1 вы можете каждый раз сортировать английскую версию и использовать xsl:number, чтобы найти исходную позицию ввода и индексировать второй список:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

  <xsl:output method="html" indent="yes" doctype-system="about:legacy-doctype"/>

  <xsl:template match="/">
    <html>
      <head>
        <title>.NET XSLT Fiddle Example</title>
      </head>
      <body>
        <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="list[lang('en')]">
      <ul>
          <xsl:apply-templates select="word">
              <xsl:sort select="."/>
          </xsl:apply-templates>
      </ul>
  </xsl:template>

  <xsl:template match="word">
      <li>
          <xsl:value-of select="."/>
      </li>
  </xsl:template>

  <xsl:template match="list[not(lang('en'))]">
      <ul>
          <xsl:variable name="non-english-list" select="word"/>
          <xsl:for-each select="../list[lang('en')]/word">
              <xsl:sort select="."/>
              <xsl:variable name="pos">
                  <xsl:number/>
              </xsl:variable>
              <xsl:apply-templates select="$non-english-list[number($pos)]"/>
          </xsl:for-each>
      </ul>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net/ 6rewNxW / 2

В XSLT 3 вы можете использовать index-of и sort: https://xsltfiddle.liberty -development.net / 6rewNxW

1 голос
/ 17 октября 2019

Вот решение XSLT 2.0 - оно выполняет только одну сортировку !

Также может быть легко преобразовано в XSLT 1.0

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

 <xsl:variable name="vDocEn" select="/"/>

 <xsl:variable name="vDocBG">
   <Lexicon>
    <Title> Български </Title>
    <Author> SafeSailor </Author>
    <Words>
        <Word> Кола </Word>
        <Word> Програмиране </Word>
        <Word> Пиши </Word>
        <Word> Бягай </Word>
        <Word> Пий </Word>
        <Word> Картоф </Word>
        <Word> Калина </Word>
        <Word> Тегло </Word>
        <Word> Група </Word>
        <Word> Хора </Word>
    </Words>
  </Lexicon>
 </xsl:variable>

 <xsl:variable name="vCompositeWords" as="element()*">
   <xsl:apply-templates select="$vDocEn/*/Words" mode="combine">
     <xsl:with-param name="pWords2" select="$vDocBG/*/Words"/>
   </xsl:apply-templates>
 </xsl:variable>

  <xsl:template match="/">
    <ul>
      <xsl:apply-templates select="$vCompositeWords"/>
    </ul>
    <ul>
      <xsl:apply-templates select="$vCompositeWords/@translation"/>
    </ul>
  </xsl:template>

  <xsl:template match="Words" mode="combine">
    <xsl:param name="pWords2" as="element()"/>

    <xsl:for-each select="Word">
      <xsl:sort/>
      <word translation="{$pWords2/Word[position() = count(current()/preceding-sibling::*)+1]}">
        <xsl:value-of select="."/>
      </word>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="word | @translation">
    <li><xsl:value-of select="."/></li>
  </xsl:template>
</xsl:stylesheet>

Когда это преобразование применяется к предоставленному документу :

<Lexicon>
    <Title> English </Title>
    <Author> SafeSailor </Author>
    <Words>
        <Word> Car </Word>
        <Word> Programming </Word>
        <Word> Write </Word>
        <Word> Run </Word>
        <Word> Drink </Word>
        <Word> Potato </Word>
        <Word> Rowan-berry </Word>
        <Word> Weight </Word>
        <Word> Group </Word>
        <Word> People </Word>
    </Words>
</Lexicon>

Требуется правильный результат :

<ul>
   <li> Car </li>
   <li> Drink </li>
   <li> Group </li>
   <li> People </li>
   <li> Potato </li>
   <li> Programming </li>
   <li> Rowan-berry </li>
   <li> Run </li>
   <li> Weight </li>
   <li> Write </li>
</ul>
<ul>
   <li> Кола </li>
   <li> Пий </li>
   <li> Група </li>
   <li> Хора </li>
   <li> Картоф </li>
   <li> Програмиране </li>
   <li> Калина </li>
   <li> Бягай </li>
   <li> Тегло </li>
   <li> Пиши </li>
</ul>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...