Mit Gruppierung Text an einem Strang ziehen und es dann testen
-
25-09-2019 - |
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?
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,
- folgt sofort einem
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>