2

そのため、この不潔な押し出しタイプセット製品では、分割されたリンクや電子メール アドレスが表示されることがあります。例:

<p>Here is some random text with an email address 
<Link>example</Link><Link>@example.com</Link> and here 
is more random text with a url 
<Link>http://www.</Link><Link>example.com</Link> near the end of the sentence.</p>

望ましい出力:

<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/">
http://www.example.com/</ext-link> near the end of the sentence.</p>

要素間の空白は発生していないように見えますが、これは 1 つの利点です。

p テンプレート内で xsl:for-each-group を使用する必要があることはわかりますが、メールと URL を区別するために、グループから結合されたテキストを contains() 関数を介して配置する方法がよくわかりません。ヘルプ?

4

2 に答える 2

0

group-adjacent を使用する場合は、次のように current-group() を単純に文字列結合できます。

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xsd"
  version="2.0">

  <xsl:template match="p">
    <xsl:copy>
      <xsl:for-each-group select="node()" group-adjacent="boolean(self::Link)">
        <xsl:choose>
          <xsl:when test="current-grouping-key()">
            <xsl:variable name="link-text" as="xsd:string" select="string-join(current-group(), '')"/>
            <xsl:choose>
              <xsl:when test="matches($link-text, '^https?://')">
                <ext-link ext-link-type="uri" xlink:href="{$link-text}">
                  <xsl:value-of select="$link-text"/>
                </ext-link>
              </xsl:when>
              <xsl:otherwise>
                <email><xsl:value-of select="$link-text"/></email>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:when>
          <xsl:otherwise>
            <xsl:apply-templates select="current-group()"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>
于 2010-02-04T13:29:17.130 に答える
0

以下は、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>
于 2010-02-03T17:40:49.903 に答える