Как отсортировать подэлемент XML с помощью XSLT - PullRequest
7 голосов
/ 21 февраля 2009

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

<?xml version="1.0"?>
<top>
  <elementA />
  <elementB />
  <contents>
      <contentitem>
          <id>3</id>
          <moretags1 />
          <moretags2 />
      </contentitem>
      <contentitem>
          <id>2</id>
          <moretags1 />
          <moretags2 />
      </contentitem>
      <contentitem>
          <id>1</id>
          <moretags1 />
          <moretags2 />
      </contentitem>
  </contents>
</top>

Мне бы хотелось, чтобы XSL-преобразование располагало элементы «contentitem» в порядке, отсортированном по их элементам «id». Все остальные теги, включая вложенные, должны быть дословно скопированы. Я уже пробовал с xsl: copy, но либо получаю двойное содержимое, либо что-то отсутствует.

Ответы [ 3 ]

7 голосов
/ 21 февраля 2009

Решение Марка Гравелла почти правильное - с небольшой проблемой, которая создает два вложенных <contents> элемента. Примечание для всех, кто дает ответы: протестируйте свои решения !

Вот правильное решение. Это преобразование :

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
<!--                                                --> 
 <xsl:strip-space elements="*"/>
<!--                                                --> 
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>
<!--                                                --> 
  <xsl:template match="contents">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:apply-templates select="contentitem">
        <xsl:sort select="id" data-type="number"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

при применении к первоначально предоставленному документу XML :

<top>
    <elementA />
    <elementB />
    <contents>
        <contentitem>
            <id>3</id>
            <moretags1 />
            <moretags2 />
        </contentitem>
        <contentitem>
            <id>2</id>
            <moretags1 />
            <moretags2 />
        </contentitem>
        <contentitem>
            <id>1</id>
            <moretags1 />
            <moretags2 />
        </contentitem>
    </contents>
</top>

дает желаемый, правильный результат :

<top>
   <elementA/>
   <elementB/>
   <contents>
      <contentitem>
         <id>1</id>
         <moretags1/>
         <moretags2/>
      </contentitem>
      <contentitem>
         <id>2</id>
         <moretags1/>
         <moretags2/>
      </contentitem>
      <contentitem>
         <id>3</id>
         <moretags1/>
         <moretags2/>
      </contentitem>
   </contents>
</top>

Обратите внимание на следующее :

  1. Использование правила идентификации для копирования всех узлов без изменений.

  2. Как шаблон идентификации переопределяется конкретным шаблоном , соответствующим элементу contents

  3. Использование инструкции <xsl:sort> для представления результатов применения шаблона в определенном порядке, возможно, отличном от порядка документов выбранных узлов для обработки.

2 голосов
/ 21 февраля 2009

Как насчет:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="/top/contents">
    <contents>
      <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select="contentitem">
          <xsl:sort data-type="number" select="id"/>
        </xsl:apply-templates>
      </xsl:copy>
    </contents>
  </xsl:template>
</xsl:stylesheet>
0 голосов
/ 21 февраля 2009

Используйте xsl: sort с xsl: for-each или xsl: apply-templates

Что-то вроде

<xsl:template match='/top/contents'>
  <xsl:apply-templates select='contentitem'>
    <xsl:sort select='id' data-type='number'/>
  </xsl:apply-templates>
</xsl:template>

Несколько элементов xsl: sort могут использоваться для нескольких ключей сортировки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...