استخدام التجميع لسحب النص معًا ثم اختباره
-
25-09-2019 - |
سؤال
لذلك في منتج التنضيد المقذوف من Grotty ، أرى أحيانًا روابط وعناوين البريد الإلكتروني التي تم تقسيمها. مثال:
<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>
لا يبدو أن المساحة البيضاء بين العناصر تحدث ، وهي نعمة واحدة.
أستطيع أن أقول إنني بحاجة إلى استخدام XSL: for-each-group ضمن قالب P ، لكن لا يمكنني رؤية كيفية وضع النص المشترك من المجموعة من خلال وظيفة تحتوي على () لتمييز رسائل البريد الإلكتروني عن عناوين URL. مساعدة؟
المحلول
إذا كنت تستخدم مجموعة مجموعة ، فيمكنك ببساطة الانضمام إلى المجموعة الحالية () كما في
<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>
نصائح أخرى
فيما يلي حل 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(preceding-sibling::node()[1][self::Link])
يعني "يجب ألا تكون العقدة السابقة مباشرة <Link>
"، على سبيل المثال: فقط <Link>
العناصر التي "الأول على التوالي".
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] ) ]
يعني
- من كل ما يلي
<Link>
S ، اختر تلك- اتبع على الفور أ
<Link>
(على سبيل المثال ، ليسوا "أولاً على التوالي") ، و - معرف
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>