XSLT条件排序

本文关键字:排序 条件 XSLT | 更新日期: 2023-09-27 18:02:12

我有以下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>

但是我需要排序,它满足以下条件:按名称排序。如果Name为空或null,我需要按LastName排序。因此,在生成的XML中,我需要以下排序:User3, User2, User1。

任何帮助都是感激的。

注::我使用ASP。NET 3.5

XSLT条件排序

我将首先使用单位变换,然后将排序应用于元素的并集(不包括那些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>

您可以使用谓词过滤器选择NameLastName元素,该过滤器使用normalize-space()过滤空元素,使用联合运算符|将它们组合并将它们与括号组合(在XSLT/XPath 2.0中创建一个序列)。然后,选择要用于排序的分组中的第一个。

此外,您可以直接使用<xsl:copy-of>,而不是重新构建<Users>元素。

<?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>