如何解决在 XSLT 中调用 mf:extract-year 的结果不允许超过一项的序列

How to solve A sequence of more than one item is not allowed as the result of call to mf:extract-year in XSLT

如何解决"A sequence of more than one item is not allowed as the result of call to mf:extract-year" 因为我的输入参数在一年中一次两次,例如(SD NY 1967) 268 F Supp 289, aff’d (2d Cir 1968) 运行 最后两个条目的 s/b 未移动。
输入

<root>
<p content-type="emCase"><named-content content-type="emEntry">A.H. Emery Co. v Marcan Prods. Corp. (SD NY 1967) 268 F Supp 289, aff&#x2019;d (2d Cir 1968) 389 F2d 11:</named-content></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. (2018) 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>
<p content-type="emCase"><named-content content-type="emEntry">Frlekin v Apple, Inc. (9th Cir 2017) 870 F3d 867:</named-content></p>
<p content-type="emCase"><named-content content-type="emEntry">Frlekin v Apple, Inc. (review granted Sept. 20, 2017, S243805) 2017 Cal Lexis 7496:</named-content></p>
<p content-type="emCase"><named-content content-type="emEntry">Bradford Technols., Inc. v NCV Software.com (ND Cal, Aug. 6, 2013, No. C 11&#x2013;04621 EDL) 2013 US Dist Lexis 111502:</named-content></p>
<p content-type="emCase"><named-content content-type="emEntry">Bradford Technols., Inc. v NCV Software.com (ND Cal, Jan. 4, 2013, No. C 11&#x2013;04621 EDL) 2013 US Dist Lexis 1592:</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 = 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="@*|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: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>

预期输出

<root>
   <p content-type="emCase">
      <named-content content-type="emEntry">A.H. Emery Co. v Marcan Prods. Corp. (SD NY 1967) 268 F Supp 289, aff’d (2d Cir 1968) 389 F2d 11:</named-content>
   </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. (2018) 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>
   <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">Frlekin v Apple, Inc. (review granted Sept. 20, 2017, S243805) 2017 Cal Lexis 7496:</named-content>
   </p>
   <p content-type="emCase">
      <named-content content-type="emEntry">Frlekin v Apple, Inc. (9th Cir 2017) 870 F3d 867:</named-content>
   </p>
   <p content-type="emCase">
      <named-content content-type="emEntry">Bradford Technols., Inc. v NCV Software.com (ND Cal, Aug. 6, 2013, No. C 11–04621 EDL) 2013 US Dist Lexis 111502:</named-content>
   </p>
   <p content-type="emCase">
      <named-content content-type="emEntry">Bradford Technols., Inc. v NCV Software.com (ND Cal, Jan. 4, 2013, No. C 11–04621 EDL) 2013 US Dist Lexis 1592:</named-content>
   </p>
</root>

代码 https://xsltfiddle.liberty-development.net/pNmC4Jf/7

您已将函数声明为

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

如果分析字符串调用找到多个匹配项(即,如果输入字符串在括号中包含多个四位数字),这将失败。所以防止错误的方法是检测是否存在多个匹配项并对其进行处理。如果输入数据中的(相关)年份超过一年,我不知道您想做什么。例如,您可以选择第一个,它只需要将 [1] 添加到您的表达式中。

为了总结我们在评论中建立的内容,提取年份的函数需要调整为 return 仅与 *:match[1] 的第一个匹配项以及括号中的数据也有一个我们需要提取并使用进一步排序键的完整日期:

<xsl:param name="months" as="xs:string*"
  select="'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'"/>

<xsl:param name="date-pattern" as="xs:string"
  select="'\((.*?)((' || string-join($months, '|') || ')\. ([0-9]{1,2}), ([0-9]{4})).*?\)'"/>

<xsl:output indent="yes"/>

<xsl:function name="mf:extract-date" as="xs:date?">
    <xsl:param name="input" as="xs:string"/>
    <xsl:sequence
        select="let $match := analyze-string($input, $date-pattern)/*:match[1]
                return 
                if ($match) 
                then xs:date(
                        $match//*:group[@nr = 5] 
                        || '-' || format-integer(index-of($months, $match//*:group[@nr = 3]), '00') 
                        || '-' || format-integer($match//*:group[@nr = 4], '00'))
                else ()"/>
</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 $date := mf:extract-date(.)
                    return if (exists($date)) then $date else 1" order="descending"/>
                <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/12