以下は、ID テンプレートに基づく XSLT 1.0 ソリューションで、<Link>
要素を特別に処理しています。
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="Link">
<xsl:if test="not(preceding-sibling::node()[1][self::Link])">
<xsl:variable name="link">
<xsl:copy-of select="
text()
|
following-sibling::Link[
preceding-sibling::node()[1][self::Link]
and
generate-id(current())
=
generate-id(
preceding-sibling::Link[
not(preceding-sibling::node()[1][self::Link])
][1]
)
]/text()
" />
</xsl:variable>
<xsl:choose>
<xsl:when test="contains($link, '://')">
<ext-link ext-link-type="uri" xlink:href="{$link}" />
</xsl:when>
<xsl:when test="contains($link, '@')">
<email>
<xsl:value-of select="$link" />
</email>
</xsl:when>
<xsl:otherwise>
<link type="unknown">
<xsl:value-of select="$link" />
</link>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
使用されている XPath 式が非常に毛むくじゃらのモンスターであることは知っていますが、XPath 1.0 で隣接する兄弟を選択するのは簡単ではありません (誰かが XPath 1.0 でそれを行う方法についてより良いアイデアを持っている場合は、私に教えてください)。
not(先行兄弟::ノード()[1][自己::リンク])
は、「直前のノードが であってはならない」ことを意味します<Link>
。たとえば、「<Link>
行の最初」の要素のみです。
次の兄弟::リンク[
前の兄弟::ノード()[1][自己::リンク]
と
生成 ID (現在 ())
=
生成 ID(
前の兄弟::リンク[
not(先行兄弟::ノード()[1][自己::リンク])
][1]
)
]
意味
- 次のすべての兄弟から
<Link>
、
- a の直後に続きます
<Link>
(たとえば、"最初の行" ではありません)。
- ノードの ID
current()
(常に<Link>
「行の最初」) は次と等しくなければなりません:
<Link>
それ自体が「行の最初」である最も近い先行
それが理にかなっていれば。
入力に適用すると、次のようになります。
<p>Here is some random text with an email address
<email>example@example.com</email> and here
is more random text with a url
<ext-link ext-link-type="uri" xlink:href="http://www.example.com" /> near the end of the sentence.</p>