XSLT условная сортировка - PullRequest
5 голосов
/ 16 июля 2011

У меня есть следующий XML:

<Users>
  <User Id="1">
    <Name>abc</Name>
    <LastName>d</LastName>
  </User>
  <User Id="2">
    <Name></Name>
    <LastName>ab</LastName>
  </User>
  <User Id="3">
    <Name>a</Name>
    <LastName>efg</LastName>
  </User>
</Users>

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

<xsl:template match="Users">
  <Users>
    <xsl:for-each select="User">
      <xsl:sort select="Name"/>
      <xsl:sort select="LastName"/>

      <User>
        <xsl:attribute name="Id">
          <xsl:value-of select="attribute::Id"/>
        </xsl:attribute>
        <Name>
          <xsl:value-of select="Name"/>
        </Name>
        <LastName>
          <xsl:value-of select="LastName"/>
        </LastName>
      </User>
    </xsl:for-each>
  </Users>
</xsl:template>

Но мне нужна сортировка, которая удовлетворяет следующему условию: сортировка по имени. Если имя пустое или пустое, мне нужно отсортировать по LastName. Поэтому в произведенном XML мне нужно следующее упорядочение: User3, User2, User1.

Любая помощь приветствуется.

П.С .: Я использую ASP.NET 3.5

Ответы [ 2 ]

3 голосов
/ 16 июля 2011

Я бы сначала использовал преобразование идентичности, а затем применил сортировку к объединению элементов (исключая те, чье Name пусто)

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

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

    <xsl:template match="Users">
        <xsl:copy>
            <xsl:apply-templates select="User">
                <xsl:sort select="Name[.!='']|LastName"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

При применении к входу, указанному в вопросе, мы получаем:

<Users>
   <User Id="3">
      <Name>a</Name>
      <LastName>efg</LastName>
   </User>
   <User Id="2">
      <Name/>
      <LastName>ab</LastName>
   </User>
   <User Id="1">
      <Name>abc</Name>
      <LastName>d</LastName>
   </User>
</Users>
1 голос
/ 16 июля 2011

Вы можете выбрать элементы Name и LastName с фильтрами предикатов, которые используют normalize-space(), чтобы отфильтровать пустые, используйте оператор объединения |, чтобы объединить их и сгруппировать с perenthesis (что создастпоследовательность в XSLT / XPath 2.0).Затем выберите первый в группе, который будет использоваться для сортировки.

Кроме того, вместо того, чтобы заново создавать элемент <Users>, вы можете просто использовать <xsl:copy-of>.

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

<xsl:template match="Users">
  <Users>
    <xsl:for-each select="User">
      <xsl:sort select="(Name[normalize-space()]|LastName[normalize-space()])[1]"/>
        <xsl:copy-of select="."/>
    </xsl:for-each>
  </Users>
</xsl:template>

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