如何从特定部分获取最大值 ref 'rid'

How to get max valued xref's 'rid' except from particular section

请建议如何从除 'Online' 部分之外的所有外部参照中获取最大 'rid' 值。通过识别最大值'rid',然后需要将属性插入到那些比最大值更高的引用中。请参阅所需的结果文本。

XML:

<article>
<body>
    <sec><title>Sections</title>
    <p>The test <xref rid="b1">1</xref>, <xref rid="b2">2</xref>, <xref rid="b3 b4 b5">3-5</xref></p></sec>
    <sec><title>Online</title><!--This section's xrefs no need to consider-->
        <p>The test <xref rid="b6">6</xref></p>
        <sec><title>Other</title>
            <p><xref rid="b1">1</xref>, <xref rid="b7 b8">7-8</xref></p>
        </sec>
    </sec><!--This section's xrefs no need to consider-->
    <sec>
        <p>Final test test</p>
        <sec><title>Third title</title><p>Last text</p></sec>
    </sec>
</body>
<bm>
    <ref id="b1">The ref01</ref>
    <ref id="b2">The ref02</ref>
    <ref id="b3">The ref03</ref>
    <ref id="b4">The ref04</ref>
    <ref id="b5">The ref05</ref>
    <ref id="b6">The ref06</ref>
    <ref id="b7">The ref07</ref>
    <ref id="b8">The ref08</ref>
</bm>
</article>

XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

<xsl:variable name="var1"><!--Variable to get the all 'rid's except sec/title contains 'Online' -->
    <xsl:for-each select="//xref[not(. is ancestor::sec[title[contains(., 'Online')]]/descendant-or-self)]/@rid">
    <!--xsl:for-each select="//xref/@rid[not(contains(ancestor::sec/title, 'Online'))]"--><!--for this xpath, error is : "XPTY0004: A sequence of more than one item is not allowed as the first argument" -->
    <!--xsl:for-each select="//xref/@rid[not(contains(ancestor::sec[1]/title, 'Online')) and not(contains(ancestor::sec[2]/title, 'Online'))]"--><!--for this xpath we are getting the required result, but there may be several nesting of 'sec's -->
        <xsl:choose>
            <xsl:when test="contains(., ' ')">
                <xsl:for-each select="tokenize(., ' ')">
                    <a><xsl:value-of select="."/></a>
                </xsl:for-each>
            </xsl:when>
            <xsl:otherwise><a><xsl:value-of select="."/></a></xsl:otherwise>
        </xsl:choose>
    </xsl:for-each>
</xsl:variable>
<xsl:variable name="varMax1">
    <xsl:for-each select="$var1/a">
        <xsl:sort select="substring-after(., 'b')" order="descending" data-type="number"/>
        <a><xsl:value-of select="."/></a>
    </xsl:for-each>
</xsl:variable>

<xsl:variable name="varMax"><!--Variable to get max valued RID -->
    <xsl:value-of select="substring-after($varMax1/a[1], 'b')"/>
</xsl:variable>

<xsl:template match="@*|node()">
    <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>

<xsl:template match="ref">
    <xsl:variable name="varID"><xsl:value-of select="substring-after(@id, 'b')"/></xsl:variable>
    <xsl:choose>
        <xsl:when test="number($varMax) lt number($varID)">
            <xsl:copy>
                <xsl:apply-templates select="@*"/>
                <xsl:attribute name="MoveRef">yes</xsl:attribute>
                <xsl:apply-templates select="node()"/>
            </xsl:copy>
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
</xsl:stylesheet>

所需结果:

<article>
<body>
    <sec><title>Sections</title>
    <p>The test <xref rid="b1">1</xref>, <xref rid="b2">2</xref>, <xref rid="b3 b4 b5">3-5</xref></p></sec>
    <sec><title>Online</title><!--This section's xrefs no need to consider-->
        <p>The test <xref rid="b6">6</xref></p>
        <sec><title>Other</title>
            <p><xref rid="b1">1</xref>, <xref rid="b7">7</xref>, <xref rid="b8">8</xref></p>
        </sec>
    </sec><!--This section's xrefs no need to consider-->
    <sec>
        <p>Final test test</p>
        <sec><title>Third title</title><p>Last text</p></sec>
    </sec>
</body>
<bm>
    <ref id="b1">The ref01</ref>
    <ref id="b2">The ref02</ref>
    <ref id="b3">The ref03</ref>
    <ref id="b4">The ref04</ref>
    <ref id="b5">The ref05</ref>
    <ref id="b6" MoveRef="yes">The ref06</ref>
    <ref id="b7" MoveRef="yes">The ref07</ref>
    <ref id="b8" MoveRef="yes">The ref08</ref>
</bm>
</article>

这里考虑数字 5 表示 'b5' rid,6 表示 'b6'...(因为字母数字)

也许您可以采用不同的方法,而不是尝试查找不在 "online" 部分中的最大 rid 属性。尤其是因为在处理字母数字字符串时并不完全清楚最大值是多少。

相反,您可以定义一个键以在 "online" 部分中按名称查找元素

<xsl:key name="online" match="sec[title = 'Online']//*" use="name()" />

然后,另一个键,查找出现在其他部分的xref个元素

<xsl:key name="other" match="xref[not(ancestor::sec/title = 'Online')]" use="name()" />

然后,你可以编写一个模板来对 ref 元素进行数学运算,并使用 xsl:if 来确定是否为其添加 MoveRef 属性:

<xsl:variable name="id" select="@id" />
<xsl:if test="key('online', 'xref')[tokenize(@rid, ' ')[. = $id]] and not(key('other', 'xref')[tokenize(@rid, ' ')[. = $id]])">

试试这个更短的 XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" indent="yes" />

    <xsl:key name="online" match="sec[title = 'Online']//*" use="name()" />
    <xsl:key name="other" match="xref[not(ancestor::sec/title = 'Online')]" use="name()" />

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="ref">
        <ref>
            <xsl:variable name="id" select="@id" />
            <xsl:if test="key('online', 'xref')[tokenize(@rid, ' ')[. = $id]] and not(key('other', 'xref')[tokenize(@rid, ' ')[. = $id]])">
                <xsl:attribute name="MoveRef" select="'Yes'" />
            </xsl:if>
            <xsl:apply-templates select="@*|node()"/>
        </ref>
    </xsl:template>
</xsl:stylesheet>

您实际上可以修改 ref 模板以将条件放入模板匹配中,如果您想要...

<xsl:template match="ref[key('online', 'xref')[tokenize(@rid, ' ')[. = current()/@id]] and not(key('other', 'xref')[tokenize(@rid, ' ')[. = current()/@id]])]">
    <ref MoveRef="Yes">
        <xsl:apply-templates select="@*|node()"/>
    </ref>
</xsl:template>