Изменение порядка элементов XML с использованием XSLT - PullRequest
1 голос
/ 01 августа 2011

У меня есть следующий фрагмент XML, который появляется во многих местах, но порядок появления элемента TYPE является случайным.Кроме того, нет гарантии, что будут доступны ВСЕ типы, например, в некоторых фрагментах могут отсутствовать Visio и / или Outlook, или отсутствуют какие-либо другие узлы:

<Applications>
    <Type Name="Word">
    <Type Name="Excel">
    <Type Name="PowerPoint">
    <Type Name="Visio">
    <Type Name="Outlook">
</Applications>

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

if EXCEL exists, 
place TYPE Excel at the top.
if WORD exists,
place TYPE Word next,
.
.
.

Я пробовал с xsl: copy, парой xsl: if и затем применил определенные шаблоны, также xsl: whens,К сожалению, ни один из них не работал для меня.Я взглянул на другой пост о переупорядочении элементов узла xml, и это не похоже на то, что я хотел (он использовал xsl: call-templates, которого у меня нет).

У меня есть кое-что, чтоначалось, как показано ниже, и я думаю, что мне нужно добавить код манипуляции выше в нижней части этого:

XML Обновлено

<xsl:template match="Applications">
    <xsl:element name="Applications">
        <xsl:element name="Type">
            <xsl:attribute name="Name">PowerPoint</xsl:attribute>
        </xsl:element>
        <xsl:element name="Type">
            <xsl:attribute name="Name">Outlook</xsl:attribute>
        </xsl:element>
        <xsl:apply-templates>
            <xsl:sort select="string-length(substring-before(';Excel;PowerPoint;Outlook;Word;Visio',@Name))"/>
        </xsl:apply-templates>
    </xsl:element>
</xsl:template>

Требуется:

<Applications>
    <Type Name="Excel">
    <Type Name="PowerPoint">
    <Type Name="Outlook">
    <Type Name="Word">
    <Type Name="Visio">
</Applications>

Но получил:

<Applications>
    <Type Name="PowerPoint">
    <Type Name="Outlook">
    <Type Name="Excel">
    <Type Name="Word">
    <Type Name="Visio">
</Applications>

Благодарю за помощь в получении этой вещи ... TIA.

Ответы [ 2 ]

7 голосов
/ 01 августа 2011

Посмотрите на инструкцию <xsl:sort>, которая используется как дочерняя для инструкций <xsl:apply-templates> или <xsl:for-each>.

Если вы хотите, чтобы что-то было отсортировано в естественном порядке (например, в цифровом или алфавитном порядке), это довольно просто, просто укажите, например, <xsl:sort select="@Name">.

Если вам нужен пользовательский порядок сортировки, есть несколько вариантов, но если ваш список невелик, попробуйте следующее:

<xsl:sort select="number-format(string-length(substring-before(
   ';Excel;Word;PowerPoint;Outlook;Visio'
   ,@Name)),'000')" />

Это в основном берет ту часть строки, которая находится перед искомой строкой, и сортирует ее по длине, заставляя три цифры обрабатывать лексографическую сортировку. Excel разрешается до 001, Word разрешается до 007 и т. Д.

В качестве альтернативы, вы можете просто перебить его так:

<xsl:template match="Application">
  <xsl:copy>
    <xsl:apply-templates select="Type[@Name='Excel']" />
    <xsl:apply-templates select="Type[@name='Word']" />
    <!-- etc.. -->
  </xsl:copy>
</xsl:template>

Все, что отсутствует, просто пропускаются, так как не к чему применять шаблон. Это проще, но немного более многословно.

0 голосов
/ 01 августа 2011

Похоже, вам нужно это:

<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="*">
  <xsl:copy>
  <xsl:copy-of select="@*"/>
  <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>


<xsl:template match="Applications">
  <xsl:copy>
  <xsl:copy-of select="@*"/>
  <xsl:apply-templates select="Type">
   <xsl:sort select="@Name"/>
  </xsl:apply-templates>
  </xsl:copy>
</xsl:template>

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