XSLT: сортировка атрибутов - PullRequest
4 голосов
/ 28 июня 2011

Мне нужна помощь с небольшим примером, чтобы я лучше понял xsl:sort.

Мои данные XML выглядят так:

<NewTerms>
    <newTerm ID="3">Zebra</newTerm>
    <newTerm ID="11">Horse</newTerm>
    <newTerm ID="1">Cat</newTerm>
    <newTerm ID="90">Lion</newTerm>
    <newTerm ID="62">Jaguar</newTerm>
    <newTerm ID="30">Cheetah</newTerm>
    <newTerm ID="55">Deer</newTerm>
    <newTerm ID="45">Buffalo</newTerm>
    <newTerm ID="15">Dog</newTerm>
</NewTerms ID="10">

, и я хочу отсортировать их поатрибут ID.У меня не работает XSL:

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

    <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>

    <xsl:template match="@*|node()[not(preceding::node()=.)]">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()[not(preceding::node()=.)]">
                <xsl:sort select="./@ID"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Я не знаю, как работает функция xsl:sort.Помогите мне в этом примере, чтобы лучше понять его.

Ответы [ 3 ]

4 голосов
/ 29 июня 2011

Ваше преобразование правильно . Вы пропустили только указание атрибута data-type, который по умолчанию равен «текст», поэтому не работает с числами.

Для получения дополнительной информации об использовании xsl:sort вы можете увидеть спецификации и недавний похожий вопрос .

Вот несколько заметок:

  • Вы можете опустить ./@ID, потому что . выбирает узел контекста, который является шаблоном по умолчанию в шаблоне
  • Вам не нужно проверять предыдущие узлы таким образом, это не имеет смысла.

Обратите внимание Вам понадобится только Преобразование личности с инструкцией сортировки.

Ваше окончательное преобразование будет выглядеть так:

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

    <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>
    <xsl:strip-space elements="*"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()">
                <xsl:sort select="@ID" data-type="number"/>
      </xsl:apply-templates>
     </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Применительно к входу (здесь немного изменен, чтобы исправить опечатку в конце тега):

<NewTerms>   
    <newTerm ID="3">Zebra</newTerm>
    <newTerm ID="11">Horse</newTerm> 
    <newTerm ID="1">Cat</newTerm>   
    <newTerm ID="90">Lion</newTerm>   
    <newTerm ID="62">Jaguar</newTerm>   
    <newTerm ID="30">Cheetah</newTerm>   
    <newTerm ID="55">Deer</newTerm>   
    <newTerm ID="45">Buffalo</newTerm>   
    <newTerm ID="15">Dog</newTerm> 
</NewTerms>

производит:

<NewTerms>
   <newTerm ID="1">Cat</newTerm>
   <newTerm ID="3">Zebra</newTerm>
   <newTerm ID="11">Horse</newTerm>
   <newTerm ID="15">Dog</newTerm>
   <newTerm ID="30">Cheetah</newTerm>
   <newTerm ID="45">Buffalo</newTerm>
   <newTerm ID="55">Deer</newTerm>
   <newTerm ID="62">Jaguar</newTerm>
   <newTerm ID="90">Lion</newTerm>
</NewTerms>
1 голос
/ 28 июня 2011

Атрибут ID в вашем теге размещения NewTerms неуместен.

Следующий XSL-скрипт сортирует ваши данные по атрибуту ID:

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

  <xsl:output method="xml"/>

  <xsl:template match="@*|node()">
    <xsl:copy-of select="." />
  </xsl:template>

  <xsl:template match="/NewTerms">
    <xsl:copy>
      <xsl:apply-templates select="newTerm">
        <xsl:sort select="@ID" data-type="number" />
      </xsl:apply-templates>
     </xsl:copy>
  </xsl:template>

</xsl:stylesheet>
0 голосов
/ 28 июня 2011

Как отмечалось в комментариях к ответу @ rsp, сортировка по умолчанию data-type - это "текст", но вам нужно "число". На самом деле вы можете использовать свою первую попытку после внесения только одного этого изменения:

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

  <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>

  <xsl:template match="@*|node()[not(preceding::node()=.)]">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()[not(preceding::node()=.)]">
        <xsl:sort select="./@ID" data-type="number" />
      </xsl:apply-templates>
     </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Это позволяет сохранить ваш (неэффективный) дубликат чека:

node()[not(preceding::node()=.)] 
...