قم بتقييد سلسلة بالأحرف المدرجة في القائمة البيضاء باستخدام XSLT 1.0

StackOverflow https://stackoverflow.com/questions/131619

  •  02-07-2019
  •  | 
  •  

سؤال

سؤال

باستخدام XSLT 1.0، في ضوء سلسلة تحتوي على أحرف عشوائية، كيف يمكنني استعادة سلسلة تتوافق مع القواعد التالية.

  1. يجب أن يكون الحرف الأول واحدًا مما يلي:a-z، A-Z، النقطتان، أو الشرطة السفلية
  2. يجب أن تكون جميع الأحرف الأخرى أيًا من تلك المذكورة أعلاه أو 0-9 أو نقطة أو واصلة
  3. إذا كان أي حرف لا يستوفي القواعد المذكورة أعلاه، فاستبدله بشرطة سفلية

خلفية

في XSLT أقوم بترجمة بعض السمات إلى عناصر، ولكنني بحاجة للتأكد من أن السمة لا تحتوي على أي قيم لا يمكن استخدامها في اسم العنصر.لا أهتم كثيرًا بسلامة السمة التي يتم تحويلها إلى الاسم طالما أنه يتم تحويلها بشكل متوقع.أنا أيضا لا أحتاج للتعويض كل حرف صالح في اسم العنصر (هناك مجموعة).

المشكلة التي كنت أواجهها كانت تتعلق بالسمات التي تحتوي على مسافات، والتي يمكن لوظيفة الترجمة تحويلها بسهولة إلى الشرطة السفلية:

translate(@name,' ','_')

ولكن بعد فترة وجيزة وجدت بعض السمات التي تستخدم الخطوط المائلة، لذلك لا بد لي من إضافة ذلك الآن أيضًا.وهذا سوف يخرج عن نطاق السيطرة بسرعة.أريد أن أكون قادرًا على تحديد قائمة بيضاء بالأحرف المسموح بها، واستبدال أي أحرف غير مسموح بها بشرطة سفلية، ولكن الترجمة تعمل عن طريق الاستبدال من القائمة السوداء.

هل كانت مفيدة؟

المحلول

أنت استطاع اكتب قالبًا متكررًا للقيام بذلك، والعمل من خلال الأحرف الموجودة في السلسلة واحدًا تلو الآخر، واختبارها وتغييرها إذا لزم الأمر.شيء مثل:

<xsl:template name="normalizeName">
  <xsl:param name="name" />
  <xsl:param name="isFirst" select="true()" />
  <xsl:if test="$name != ''">
    <xsl:variable name="first" select="substring($name, 1, 1)" />
    <xsl:variable name="rest" select="substring($name, 2)" />
    <xsl:choose>
      <xsl:when test="contains('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:_', $first) or
                      (not($first) and contains('0123456789.-', $first))">
        <xsl:value-of select="$first" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:text>_</xsl:text>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:call-template name="normalizeName">
      <xsl:with-param name="name" select="$rest" />
      <xsl:with-param name="isFirst" select="false()" />
    </xsl:call-template>
  </xsl:if>
</xsl:template>

ومع ذلك، هناك طريقة أقصر للقيام بذلك إذا كنت مستعدًا لبعض عمليات الاختراق.أولا قم بتعريف بعض المتغيرات:

<xsl:variable name="underscores"
  select="'_______________________________________________________'" />
<xsl:variable name="initialNameChars"
  select="'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:_'" />
<xsl:variable name="nameChars"
  select="concat($initialNameChars, '0123456789.-')" />

الآن التقنية هي أخذ الاسم وتحديد الشخصيات التي ليست كذلك قانوني عن طريق استبدال جميع الأحرف الموجودة في الاسم نكون قانوني مع لا شيء.يمكنك القيام بذلك مع translate() وظيفة.بمجرد حصولك على مجموعة الأحرف غير القانونية التي تظهر في السلسلة، يمكنك استبدالها بشرطات سفلية باستخدام translate() وظيفة مرة أخرى.وهنا القالب:

<xsl:template name="normalizeName">
  <xsl:param name="name" />
  <xsl:variable name="first" select="substring($name, 1, 1)" />
  <xsl:variable name="rest" select="substring($name, 2)" />
  <xsl:variable name="illegalFirst"
    select="translate($first, $initialNameChars, '')" />
  <xsl:variable name="illegalRest"
    select="translate($rest, $nameChars, '')" />
  <xsl:value-of select="concat(translate($first, $illegalFirst, $underscores),
                               translate($rest, $illegalRest, $underscores))" />
</xsl:template>

الشيء الوحيد الذي عليك الانتباه إليه هو أن سلسلة الشرطات السفلية يجب أن تكون طويلة بما يكفي لتغطية كافة الأحرف غير القانونية التي قد تظهر ضمن اسم واحد.إن جعله بنفس طول الاسم الأطول الذي من المحتمل أن تصادفه سوف يفي بالغرض (على الرغم من أنه من المحتمل أن تفلت من كونه أقصر كثيرًا).

نصائح أخرى

بقدر ما أعلم، لا يحتوي XSLT 1.0 على أداة مدمجة لهذا الغرض.يسمح لك XSLT 2.0 بذلك استخدم التعابير المنطقية, ، على الرغم من أنني متأكد من أنكم جميعًا على دراية بذلك.

إذا كنت تستخدم محلل MS، فيمكنك كتابة مكتبات امتداد .NET التي يمكنك الاستفادة منها في XSLT الخاص بك وقد كتبت عن هذا منذ بضعة أشهر هنا.

إذا كنت تستخدم شيئًا مثل Saxon، فأنا متأكد تمامًا من أنهم يقدمون أيضًا طرقًا لترميز الامتدادات الخاصة بك، وقد يكون لديهم بالفعل امتداد خاص بهم بالفعل، لكنني لست على دراية بهذا المحرك.

أتمنى أن يساعدك هذا.

كبديل آخر، هناك دالة سلسلة قد تناسبك في مكتبة XSLT القياسية. http://xsltsl.sourceforge.net/string.html#template.str:string-match

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top