I am trying to sorting based on Text - XSLT

前端 未结 3 1579
一个人的身影
一个人的身影 2021-01-23 06:31

I am trying to sorting on text based first text should be upper case then other start with first letter caps or small letter.
Input XML

            


        
相关标签:
3条回答
  • 2021-01-23 06:48

    To sort upper-case letters before lower-case letters, use the case-order attribute of xsl:sort.

    Here's a simplified example:

    XSLT

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <xsl:template match="/root">
        <xsl:copy>
            <xsl:for-each select="p">
                <xsl:sort select="named-content" data-type="text" order="ascending" case-order= "upper-first"/>
                <xsl:copy>
                    <xsl:apply-templates/>
                </xsl:copy>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
    
    </xsl:stylesheet>
    

    Result

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
      <p>B.K.B. v Maui Police Dep’t (9th Cir 2002) 276 F3d 1091:</p>
      <p>BTS, USA, Inc. v Executive Perspectives, LLC (Conn. Super, Oct. 16, 2014, No. X10CV116010685) 2014 Conn Super Lexis 2644, aff’d (Conn App 2016) 142 A3d 342:</p>
      <p>Babcock v Butler County (3d Cir 2015) 806 F3d 153:</p>
      <p>Buxbom v Smith (1944) 23 C2d 535:</p>
      <p>Byrd v Roadway Express, Inc. (5th Cir 1982) 687 F2d 85:</p>
      <p>buySAFE, Inc. v Google, Inc. (Fed Cir 2014) 765 F3d 1350:</p>
    </root>
    

    Added:

    I too do not understand what logic you want to implement to get the output you show.

    I am able to get the same output by sorting the nodes in the following order:

    • nodes that begin with initials come first;
    • then sort alphabetically, ignoring case.

    XSLT 2.0

    <xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <!-- identity transform -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="/root">
        <xsl:copy>
            <xsl:apply-templates select="p">
                <xsl:sort select="number(matches(named-content, '^[A-Z](\.|[A-Z]|$)'))" data-type="number" order="descending"/>
                <xsl:sort select="named-content" data-type="text" order="ascending" lang="en"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
    

    Demo: https://xsltfiddle.liberty-development.net/a9GPfN

    </xsl:stylesheet>
    
    0 讨论(0)
  • 2021-01-23 06:54

    Not sure I get your question, is this what you are trying to do :

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="2.0">
    
      <xsl:output method="xml" indent="yes"/>
    
      <xsl:template match="root">
          <xsl:copy>
              <xsl:apply-templates select="p">
                  <xsl:sort select="named-content"/>
              </xsl:apply-templates>
          </xsl:copy>
      </xsl:template>
    
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>
    
    </xsl:stylesheet>
    

    See it working here : https://xsltfiddle.liberty-development.net/bEzknsV

    0 讨论(0)
  • 2021-01-23 07:15

    Does the following meet your requirements? (Requirements were hard to understand. I assume there is more simple and faster XSLT code to accomplish this task ...)

    It evaluates for the given input to the expected output https://xsltfiddle.liberty-development.net/pNmC4J7

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        exclude-result-prefixes="#all"
        version="2.0">
    
      <xsl:output method="xml" indent="yes"/>
    
        <xsl:template match="@*|node()">
          <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
          </xsl:copy>
        </xsl:template>
    
        <xsl:key name="psStartingWithChar" match="p" use="upper-case(substring(translate(named-content/text(), translate(named-content/text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', ''), ''),1,1))"/>
    
        <xsl:template match="root">
            <xsl:variable name="ctxt">
                <xsl:copy-of select="."/>
            </xsl:variable>
    
            <xsl:variable name="temp">
                <xsl:for-each select="string-to-codepoints('ABCDEFGHIJKLMNOPQRSTUVWXYZ')">
                    <xsl:variable name="ch" select="codepoints-to-string(.)"/>
    
                    <xsl:variable name="root">
                        <xsl:for-each select="$ctxt">
                            <root>
                                <xsl:for-each select="key('psStartingWithChar',$ch)">
                                    <xsl:copy-of select="."/>
                                </xsl:for-each>
                            </root>
                        </xsl:for-each>
                    </xsl:variable>
    
                    <xsl:for-each select="$root/root">
                        <xsl:copy>
                            <xsl:for-each select="p[named-content[@content-type='emEntry'][string-length(.)=1 or matches(translate(., translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', ''), ''), '^([^a-z]{2,})')]]">
                                <xsl:sort data-type="text" order="ascending"/>
                                <xsl:copy>
                                    <xsl:apply-templates select="@*|node()"/>
                                </xsl:copy>
                            </xsl:for-each>
                            <xsl:for-each select="p[named-content[@content-type='emEntry'][not(string-length(.)=1 or matches(translate(., translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', ''), ''), '^([^a-z]{2,})'))]]">
                                <xsl:sort data-type="text" case-order= "upper-first" order="ascending"/>
                                <xsl:copy>
                                    <xsl:apply-templates select="@*|node()"/>
                                </xsl:copy>
                            </xsl:for-each>
                        </xsl:copy>
                    </xsl:for-each>
                </xsl:for-each>
            </xsl:variable>
    
            <root>
                <xsl:copy-of select="$temp/root/*"/>
            </root>
       </xsl:template>
    
    </xsl:stylesheet>
    
    0 讨论(0)
提交回复
热议问题