如何从特定部分获取最大值 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>
请建议如何从除 '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>