如何在 XSLT 中使用组形容词对数据进行排序
How to sort data with group-adjecment in XSLT
如何对数据降序排列?在括号中,一些年份字符串是相同的,但在年份字符串之前有一些文本,例如Mendoza v Nordstrom, Inc. (2017)
和 Mendoza v Nordstrom, Inc. (9th Cir 2017)
。我们只希望在相同文本之前进行更改,然后我使用 substring-before(named-content[@content-type = 'emEntry'], '(')
。如果年份不同,则代码工作正常,例如AFL-CIO v Unemployment Ins. Appeals Bd. (1994)
和 AFL-CIO v Unemployment Ins. Appeals Bd. (1996)
。如果同一年到来,则代码无效。请检查最后两个条目
输入XML
<root>
<p content-type="emLetHead">A</p>
<p content-type="emCase"><named-content content-type="emEntry">A.M. v Albertsons, LLC (2009) 178 CA4th 455:</named-content></p>
<p content-type="emCase"><named-content content-type="emEntry">ABBA Rubber Co. v Seaquist (1991) 235 CA3d 1:</named-content></p>
<p content-type="emCase"><named-content content-type="emEntry">AFL-CIO v Unemployment Ins. Appeals Bd. (1994) 23 CA4th 51:</named-content></p>
<p content-type="emCase"><named-content content-type="emEntry">AFL-CIO v Unemployment Ins. Appeals Bd. (1996) 13 C4th 1017:</named-content></p>
<p content-type="emCase"><named-content content-type="emEntry">Mendoza v Nordstrom, Inc. (2017) 2 C5th 1074:</named-content></p>
<p content-type="emCase"><named-content content-type="emEntry">Mendoza v Nordstrom, Inc. (9th Cir 2017) 865 F3d 1261:</named-content></p>
</root>
XSLT:
<xsl:function name="mf:extract-year" as="xs:integer?">
<xsl:param name="input" as="xs:string"/>
<xsl:sequence
select="analyze-string($input, '\(.*?([0-9]{4}).*\)')/*:match/*:group[@nr = 1]/xs:integer(.)"/>
</xsl:function>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root">
<xsl:copy>
<xsl:for-each-group select="p" group-adjacent="substring-before(named-content[@content-type = 'emEntry'], '(')">
<xsl:apply-templates select="current-group()">
<xsl:sort select="let $year := mf:extract-year(.)
return if ($year) then -$year else 1"/>
</xsl:apply-templates>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
预期输出
<root>
<p content-type="emLetHead">A</p>
<p content-type="emCase">
<named-content content-type="emEntry">A.M. v Albertsons, LLC (2009) 178 CA4th 455:</named-content>
</p>
<p content-type="emCase">
<named-content content-type="emEntry">ABBA Rubber Co. v Seaquist (1991) 235 CA3d 1:</named-content>
</p>
<p content-type="emCase">
<named-content content-type="emEntry">AFL-CIO v Unemployment Ins. Appeals Bd. (1996) 13 C4th 1017:</named-content>
</p>
<p content-type="emCase">
<named-content content-type="emEntry">AFL-CIO v Unemployment Ins. Appeals Bd. (1994) 23 CA4th 51:</named-content>
</p>
<p content-type="emCase">
<named-content content-type="emEntry">Mendoza v Nordstrom, Inc. (9th Cir 2017) 865 F3d 1261:</named-content>
</p>
<p content-type="emCase">
<named-content content-type="emEntry">Mendoza v Nordstrom, Inc. (2017) 2 C5th 1074:</named-content>
</p>
</root>
也许提取 ()
中的任何内容并作为字符串排序就足够了:
<xsl:function name="mf:extract-sort" as="xs:string?">
<xsl:param name="input" as="xs:string"/>
<xsl:sequence
select="analyze-string($input, '\((.*?)\)')/*:match/*:group[@nr = 1]"/>
</xsl:function>
<xsl:template match="root">
<xsl:copy>
<xsl:for-each-group select="p" group-adjacent="substring-before(named-content[@content-type = 'emEntry'], '(')">
<xsl:apply-templates select="current-group()">
<xsl:sort select="let $sort := mf:extract-sort(.)
return if ($sort) then $sort else 1" order="descending"/>
</xsl:apply-templates>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
https://xsltfiddle.liberty-development.net/pNmC4Jf
或者可能使用多个 xsl:sort
用于所需的不同部分 order/priority:
<xsl:function name="mf:extract-year" as="xs:integer?">
<xsl:param name="input" as="xs:string"/>
<xsl:sequence
select="analyze-string($input, '\((.*?)([0-9]{4})\)')/*:match/*:group[@nr = 2]"/>
</xsl:function>
<xsl:function name="mf:extract-sort" as="xs:string?">
<xsl:param name="input" as="xs:string"/>
<xsl:sequence
select="analyze-string($input, '\((.*?)\)')/*:match/*:group[@nr = 1]"/>
</xsl:function>
<xsl:template match="root">
<xsl:copy>
<xsl:for-each-group select="p" group-adjacent="substring-before(named-content[@content-type = 'emEntry'], '(')">
<xsl:apply-templates select="current-group()">
<xsl:sort select="let $year := mf:extract-year(.)
return if ($year) then -$year else 1"/>
<xsl:sort select="let $sort := mf:extract-sort(.)
return if ($sort) then $sort else 1" order="descending"/>
</xsl:apply-templates>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
如何对数据降序排列?在括号中,一些年份字符串是相同的,但在年份字符串之前有一些文本,例如Mendoza v Nordstrom, Inc. (2017)
和 Mendoza v Nordstrom, Inc. (9th Cir 2017)
。我们只希望在相同文本之前进行更改,然后我使用 substring-before(named-content[@content-type = 'emEntry'], '(')
。如果年份不同,则代码工作正常,例如AFL-CIO v Unemployment Ins. Appeals Bd. (1994)
和 AFL-CIO v Unemployment Ins. Appeals Bd. (1996)
。如果同一年到来,则代码无效。请检查最后两个条目
输入XML
<root>
<p content-type="emLetHead">A</p>
<p content-type="emCase"><named-content content-type="emEntry">A.M. v Albertsons, LLC (2009) 178 CA4th 455:</named-content></p>
<p content-type="emCase"><named-content content-type="emEntry">ABBA Rubber Co. v Seaquist (1991) 235 CA3d 1:</named-content></p>
<p content-type="emCase"><named-content content-type="emEntry">AFL-CIO v Unemployment Ins. Appeals Bd. (1994) 23 CA4th 51:</named-content></p>
<p content-type="emCase"><named-content content-type="emEntry">AFL-CIO v Unemployment Ins. Appeals Bd. (1996) 13 C4th 1017:</named-content></p>
<p content-type="emCase"><named-content content-type="emEntry">Mendoza v Nordstrom, Inc. (2017) 2 C5th 1074:</named-content></p>
<p content-type="emCase"><named-content content-type="emEntry">Mendoza v Nordstrom, Inc. (9th Cir 2017) 865 F3d 1261:</named-content></p>
</root>
XSLT:
<xsl:function name="mf:extract-year" as="xs:integer?">
<xsl:param name="input" as="xs:string"/>
<xsl:sequence
select="analyze-string($input, '\(.*?([0-9]{4}).*\)')/*:match/*:group[@nr = 1]/xs:integer(.)"/>
</xsl:function>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root">
<xsl:copy>
<xsl:for-each-group select="p" group-adjacent="substring-before(named-content[@content-type = 'emEntry'], '(')">
<xsl:apply-templates select="current-group()">
<xsl:sort select="let $year := mf:extract-year(.)
return if ($year) then -$year else 1"/>
</xsl:apply-templates>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
预期输出
<root>
<p content-type="emLetHead">A</p>
<p content-type="emCase">
<named-content content-type="emEntry">A.M. v Albertsons, LLC (2009) 178 CA4th 455:</named-content>
</p>
<p content-type="emCase">
<named-content content-type="emEntry">ABBA Rubber Co. v Seaquist (1991) 235 CA3d 1:</named-content>
</p>
<p content-type="emCase">
<named-content content-type="emEntry">AFL-CIO v Unemployment Ins. Appeals Bd. (1996) 13 C4th 1017:</named-content>
</p>
<p content-type="emCase">
<named-content content-type="emEntry">AFL-CIO v Unemployment Ins. Appeals Bd. (1994) 23 CA4th 51:</named-content>
</p>
<p content-type="emCase">
<named-content content-type="emEntry">Mendoza v Nordstrom, Inc. (9th Cir 2017) 865 F3d 1261:</named-content>
</p>
<p content-type="emCase">
<named-content content-type="emEntry">Mendoza v Nordstrom, Inc. (2017) 2 C5th 1074:</named-content>
</p>
</root>
也许提取 ()
中的任何内容并作为字符串排序就足够了:
<xsl:function name="mf:extract-sort" as="xs:string?">
<xsl:param name="input" as="xs:string"/>
<xsl:sequence
select="analyze-string($input, '\((.*?)\)')/*:match/*:group[@nr = 1]"/>
</xsl:function>
<xsl:template match="root">
<xsl:copy>
<xsl:for-each-group select="p" group-adjacent="substring-before(named-content[@content-type = 'emEntry'], '(')">
<xsl:apply-templates select="current-group()">
<xsl:sort select="let $sort := mf:extract-sort(.)
return if ($sort) then $sort else 1" order="descending"/>
</xsl:apply-templates>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
https://xsltfiddle.liberty-development.net/pNmC4Jf
或者可能使用多个 xsl:sort
用于所需的不同部分 order/priority:
<xsl:function name="mf:extract-year" as="xs:integer?">
<xsl:param name="input" as="xs:string"/>
<xsl:sequence
select="analyze-string($input, '\((.*?)([0-9]{4})\)')/*:match/*:group[@nr = 2]"/>
</xsl:function>
<xsl:function name="mf:extract-sort" as="xs:string?">
<xsl:param name="input" as="xs:string"/>
<xsl:sequence
select="analyze-string($input, '\((.*?)\)')/*:match/*:group[@nr = 1]"/>
</xsl:function>
<xsl:template match="root">
<xsl:copy>
<xsl:for-each-group select="p" group-adjacent="substring-before(named-content[@content-type = 'emEntry'], '(')">
<xsl:apply-templates select="current-group()">
<xsl:sort select="let $year := mf:extract-year(.)
return if ($year) then -$year else 1"/>
<xsl:sort select="let $sort := mf:extract-sort(.)
return if ($sort) then $sort else 1" order="descending"/>
</xsl:apply-templates>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>