XSLT 2.0 および関連する仕様の正誤表を作成するために使用されるスタイルシートについて、これと同様の目的でコードを書いたことがあります。あなたはそれがあなたにいくつかのアイデアを与えることに気付くかもしれません。これには、複数の正誤表によって「影響を受ける」仕様内のテキストがないことを確認するロジックが含まれています。コードは次のとおりです (正誤表を定義する XML ドキュメントには、ベース ドキュメントのどのセクションが「影響を受ける」かを示す XPath 式が含まれているため、saxon:evaluate を使用します)。
ここでの主な目的は、2 つの XPath 式がオーバーラップするノードを選択するかどうかを判断することではなく、N 個のそのような式にオーバーラップがあるかどうかを判断することです。ここで、式は事前に知られていません。式のすべてのペア間のオーバーラップを探すことなく、これを実行したいと考えています。
count($x) != count($x/.) という興味深い表現があります。ここで ($x/.) は、ノード シーケンスから重複ノードを強制的に削除するために使用されます。したがって、テストでは、重複を削除するとノードが削除されるかどうか、つまり $x に重複が含まれるかどうかを尋ねます。
<!-- The following template checks that there is no element in the source document
that is replaced or deleted by more than one erratum -->
<xsl:template name="check-for-conflicts">
<xsl:variable name="directly-affected-elements"
select="er:eval-all(/er:errata/er:erratum[not(@superseded)]//er:old-text[not(starts-with(@action, 'insert-'))])"/>
<xsl:variable name="all-affected-elements"
select="for $e in $directly-affected-elements return $e/descendant-or-self::*"/>
<xsl:if test="count($all-affected-elements) != count($all-affected-elements/.)">
<!-- we now know there are duplicates, we just need to identify them... -->
<xsl:for-each-group select="$all-affected-elements" group-by="generate-id()">
<xsl:if test="count(current-group()) gt 1">
<xsl:variable name="id" select="(ancestor::*/@id)[last()]"/>
<xsl:variable name="section" select="$spec/key('id',$id)"/>
<xsl:variable name="section-number">
<xsl:number select="$section" level="multiple" count="div1|div2|div3|div4"/>
</xsl:variable>
<xsl:variable name="loc" select="er:location($section, .)"/>
<p style="color:red">
<xsl:text>WARNING: In </xsl:text>
<xsl:value-of select="$section-number, $section/head"/>
<xsl:text> (</xsl:text>
<xsl:value-of select="$loc"/>
<xsl:text>) Element is affected by more than one change</xsl:text>
</p>
</xsl:if>
</xsl:for-each-group>
</xsl:if>
</xsl:template>
<!-- Support function for the check-for-conflicts template.
This function builds a list (retaining duplicates) of all elements
in the source document directly affected by a replacement or deletion.
"Directly affected" means that the element is explicitly selected for replacement
or deletion; the descendants of this element are indirectly affected. -->
<xsl:function name="er:eval-all" as="element()*">
<xsl:param name="in" as="element(er:old-text)*"/>
<xsl:for-each select="$in">
<xsl:variable name="id" select="@ref"/>
<xsl:variable name="section" select="$spec/key('id',$id)"/>
<xsl:variable name="exp" select="@select"/>
<xsl:variable name="nodes" select="$section/saxon:evaluate($exp)"/>
<xsl:sequence select="$nodes"/>
</xsl:for-each>
</xsl:function>