代码之家  ›  专栏  ›  技术社区  ›  Patrick

不在列表中的值的XSLT排序列表语法

  •  0
  • Patrick  · 技术社区  · 3 年前

    多亏了这个网站,我才知道如何在子元素上创建特定的顺序排序(我不经常使用XSLT)。

    我遇到的问题是,当某个东西不在清单上时,它不再尊重任何排序。

    所需的结果是,有5个定义的子元素始终按特定顺序位于顶部,其他任何元素都会紧随其后,因为每天都会创建数百种可能性。之后的排序并不重要,重要的是定义的5始终位于顶部。

    列出所有元素值时的XML示例:

    <Root>
        <Parent>
            <Child>
                <FieldValue>SAMPLE1</FieldValue>
            </Child>
        </Parent>
        <Parent>
            <Child>
                <FieldValue>SAMPLE2</FieldValue>
            </Child>
        </Parent>
            <Parent>
            <Child>
                <FieldValue>SAMPLE3</FieldValue>
            </Child>
        </Parent>
        <Parent>
            <Child>
                <FieldValue>SAMPLE4</FieldValue>
            </Child>
        </Parent>       
    </Root>
    

    XSLT

    <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:param name="pSortingValues" select="'SAMPLE2,SAMPLE1,SAMPLE4,SAMPLE3'"/>
     <xsl:variable name="vSortingValues" select=
      "concat(',', $pSortingValues, ',')"/>
    
        <xsl:template match="node()|@*">
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
        </xsl:template>
    
        <xsl:template match="/*">
          <xsl:copy>
           <xsl:apply-templates select="@*"/>
           <xsl:apply-templates select="*">
            <xsl:sort data-type="number" select=
            "string-length(substring-before($vSortingValues,concat(',',Child/FieldValue,',')))"/>
           </xsl:apply-templates>
          </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>
    

    后果

    <Root>
       <Parent>
          <Child>
             <FieldValue>SAMPLE2</FieldValue>
          </Child>
       </Parent>
       <Parent>
          <Child>
             <FieldValue>SAMPLE1</FieldValue>
          </Child>
       </Parent>
       <Parent>
          <Child>
             <FieldValue>SAMPLE4</FieldValue>
          </Child>
       </Parent>
       <Parent>
          <Child>
             <FieldValue>SAMPLE3</FieldValue>
          </Child>
       </Parent>
    </Root>
    

    任何想法都将不胜感激,到目前为止我还没有成功。我使用变量和if语句的尝试以惊人的失败告终

    2 回复  |  直到 3 年前
        1
  •  0
  •   Heiko Theißen    3 年前

    (XSLT 1.0)

    string-length(substring-before(...)) 如果找不到字段值,则为0。如果您希望在末尾添加这样的条目,请使用

    <xsl:variable name="vSortingValues"
      select="concat(',', $pSortingValues, ', ')"/>
    

    和

    <xsl:sort select="string-length(substring-after(...))" order="descending"/>
    

    相反末端的额外空间 $vSortingValues 确保 substring-after 如果找到字段值,则至少包含一个字符(此尾部空格),并且字段值越长,在列表中出现的时间越早。不在列表中的字段值给出一个空字符串,因此按降序排在最后。

        2
  •  0
  •   y.arazim    3 年前

    另一种可能性:

    <xsl:template match="/Root">
        <xsl:copy>
            <xsl:apply-templates select="Parent">
                <xsl:sort select="contains($vSortingValues, concat(',', Child/FieldValue, ','))" order="descending"/>
                <xsl:sort select="string-length(substring-before($vSortingValues, concat(',', Child/FieldValue, ',')))" data-type="number" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>