Frage

Also in diesem grotty extrudiert Produkt Satz, ich sehe manchmal Links und E-Mail-Adressen, die Split auseinander waren. Beispiel:

<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>

Gewünschte Ausgabe:

<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>

Leerzeichen zwischen den Elementen scheint nicht zu kommen, was ein Segen ist.

Ich kann sagen, ich brauche einen xsl zu verwenden: for-each-Gruppe innerhalb der p-Vorlage, aber ich kann nicht ganz sehen, wie die kombinierte Text setzt aus der Gruppe durch die contains () Funktion, um E-Mails zu unterscheiden von URLs. Hilfe?

War es hilfreich?

Lösung

Wenn Sie group-adjacent dann können Sie einfach string-join die aktuelle Gruppe (), wie in

<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>

Andere Tipps

Hier ist eine XSLT 1.0-Lösung auf der Identity-Vorlage basiert, mit einem besonderen Behandlung für <Link> Elemente.

<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>

Ich weiß, dass verwendet XPath-Ausdrücke sind einige ziemlich haarige Monster, aber benachbarte Geschwister Auswahl ist nicht leicht, in XPath 1.0 (wenn jemand eine bessere Idee hat, wie es in XPath tun 1.0, gehen Sie voran und sagen Sie mir).

not(preceding-sibling::node()[1][self::Link])

Mittel „der unmittelbar vorhergehenden Knoten darf kein <Link> sein“, z.B .: <Link> nur Elemente, die „erste in einer Reihe“.

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]
  )
]

Mittel

  • von allen following-sibling <Link>s, wählen Sie diejenigen, die
    • folgt sofort einem <Link> (z.B. sind sie nicht „zuerst in einer Reihe“ bezeichnet) und
    • die ID des current() Knoten (immer ein <Link>, die „erste in einer Reihe“ ist) müssen gleich sein zu:
    • der nächstgelegene vorangehende <Link> dass sich „erst in einer Reihe“ ist,

Wenn das macht Sinn.

Angewandt auf Ihre Eingabe, die ich erhalten:

<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>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top