سؤال

لذلك في منتج التنضيد المقذوف من 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>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top