この変換:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p/text()[matches(., 'Story [0-9]+(\.[0-9]+)')]">
<xsl:variable name="vCur" select="."/>
<xsl:variable name="pContent" select="string(.)"/>
<xsl:analyze-string select="$pContent" regex="Story [0-9]*\.[0-9]*" flags="i">
<xsl:matching-substring>
<xsl:variable name="figureToTargetId">
<xsl:analyze-string select="." regex="[0-9]*\.[0-9]*">
<xsl:matching-substring>
<xsl:value-of select="concat('s',.)"/>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:variable>
<a href="#{$figureToTargetId}">
<xsl:value-of select="."/>
<xsl:if test="not(matches($vCur, 'Story [0-9]+(\.[0-9]+).+$'))">
<xsl:sequence select="$vCur/following-sibling::*[1]"/>
</xsl:if>
</a>
</xsl:matching-substring>
<xsl:non-matching-substring><xsl:value-of select="."/></xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
<xsl:template match=
"p/*[preceding-sibling::node()[1]
[self::text()
and
matches(., 'Story [0-9]+(\.[0-9]+)$')]
]"/>
</xsl:stylesheet>
このドキュメントに適用した場合(両方の興味深いケースを含むように拡張された提供されたドキュメント):
<t>
<p>Little Red Riding Hood (Story 3.1) </p>
<p>Jack goes up the hill (Story 3.1<i>a</i>) to fetch a pail of water.</p>
</t>
必要な正しい結果を生成します:
<t>
<p>Little Red Riding Hood (<a href="#s3.1">Story 3.1</a>) </p>
<p>Jack goes up the hill (<a href="#s3.1">Story 3.1<i>a</i>
</a>) to fetch a pail of water.</p>
</t>
説明:
一致した部分文字列が現在のテキスト ノードの接尾辞であるかどうかを確認します。そうである場合は、最初に続く兄弟要素もコピーします。
更新:
コメントで、OP は新しい追加の要件を設定しました。これも に変更<i>
し<em>
ます。
これには、上記のソリューションをわずかに更新するだけで済みます。
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p/text()[matches(., 'Story [0-9]+(\.[0-9]+)')]">
<xsl:variable name="vCur" select="."/>
<xsl:variable name="pContent" select="string(.)"/>
<xsl:analyze-string select="$pContent" regex="Story [0-9]*\.[0-9]*" flags="i">
<xsl:matching-substring>
<xsl:variable name="figureToTargetId">
<xsl:analyze-string select="." regex="[0-9]*\.[0-9]*">
<xsl:matching-substring>
<xsl:value-of select="concat('s',.)"/>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:variable>
<a href="#{$figureToTargetId}">
<xsl:value-of select="."/>
<xsl:if test="not(matches($vCur, 'Story [0-9]+(\.[0-9]+).+$'))">
<xsl:apply-templates mode="match" select="$vCur/following-sibling::*[1]"/>
</xsl:if>
</a>
</xsl:matching-substring>
<xsl:non-matching-substring><xsl:value-of select="."/></xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
<xsl:template match=
"p/*[preceding-sibling::node()[1]
[self::text()
and
matches(., 'Story [0-9]+(\.[0-9]+)$')]
]"/>
<xsl:template mode="match" match=
"p/i[preceding-sibling::node()[1]
[self::text()
and
matches(., 'Story [0-9]+(\.[0-9]+)$')]
]">
<em><xsl:apply-templates/></em>
</xsl:template>
</xsl:stylesheet>