النوع الأبجدي الرقمي على قيمة السلسلة المختلطة

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

  •  27-09-2019
  •  | 
  •  

سؤال

إعطاء مقتطف XML من:

<forms>
<FORM lob="BO" form_name="AI OM 10"/>
<FORM lob="BO" form_name="CL BP 03 01"/>
<FORM lob="BO" form_name="AI OM 107"/>
<FORM lob="BO" form_name="CL BP 00 02"/>
<FORM lob="BO" form_name="123 DDE"/>
<FORM lob="BO" form_name="CL BP 00 02"/>
<FORM lob="BO" form_name="AI OM 98"/>
</forms>

أحتاج إلى فرز العقد النموذجية بواسطة form_name أبجديًا ، بحيث يتم تجميع جميع النماذج التي تحتوي على "ai om" في form_name معًا ، ثم داخلها في ترتيب رقمي بواسطة الأعداد الصحيحة (نفس النماذج الأخرى).

يمكن أن يكون Form_Name مفتوحًا حيث يمكن أن تكون الحروف والأرقام في أي ترتيب:

xx ## ##
xx xx ##
xx xx ###
xx xx ## ##
xx ###
xx xxxx
## xxx
xxx ###

ما أعتقد أنه يحتاج إلى حدوث ذلك هو أن السلسلة تحتاج إلى تقسيم بين ألفا والرقم. من المحتمل أن يتم فرز الجزء الرقمي مع أي مسافات تمت إزالتها.

أنا في حيرة بشأن كيفية تقسيم السلسلة ثم تغطية جميع مجموعات الفرز/التجميع بالنظر إلى أنه لا توجد قواعد حول تنسيق "form_name".

نحن نستخدم XSLT 2.0. شكرًا.

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

المحلول

هذا التحول:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vDigits" select="'0123456789 '"/>
 <xsl:variable name="vAlpha" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ '"/>

 <xsl:template match="/*">
  <forms>
   <xsl:for-each select="FORM">
    <xsl:sort select="translate(@form_name,$vDigits,'')"/>
    <xsl:sort select="translate(@form_name,$vAlpha,'')"
        data-type="number"/>
    <xsl:copy-of select="."/>
   </xsl:for-each>
  </forms>
 </xsl:template>
</xsl:stylesheet>

عند تطبيقه على مستند XML المقدم:

<forms>
    <FORM lob="BO" form_name="AI OM 10"/>
    <FORM lob="BO" form_name="CL BP 03 01"/>
    <FORM lob="BO" form_name="AI OM 107"/>
    <FORM lob="BO" form_name="CL BP 00 02"/>
    <FORM lob="BO" form_name="123 DDE"/>
    <FORM lob="BO" form_name="CL BP 00 02"/>
    <FORM lob="BO" form_name="AI OM 98"/>
</forms>

تنتج النتيجة الصحيحة المطلوبة:

<forms>
    <FORM lob="BO" form_name="AI OM 10"/>
    <FORM lob="BO" form_name="AI OM 98"/>
    <FORM lob="BO" form_name="AI OM 107"/>
    <FORM lob="BO" form_name="CL BP 00 02"/>
    <FORM lob="BO" form_name="CL BP 00 02"/>
    <FORM lob="BO" form_name="CL BP 03 01"/>
    <FORM lob="BO" form_name="123 DDE"/>
</forms>

القيام مذكرة:

  1. اثنين <xsl:sort> تعليمات تنفيذ الفرز ثنائي الطور

  2. XPath translate() يتم استخدام الوظيفة لإنتاج إما مفتاح Sort-alpha فقط أو مفتاح الفرز فقط.

نصائح أخرى

ورقة الأنماط هذه:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="forms">
        <xsl:apply-templates>
            <xsl:sort select="normalize-space(
                                translate(@form_name,
                                          '0123456789',
                                          ''))"/>
            <xsl:sort select="substring-before(
                                concat(
                                  normalize-space(
                                    translate(@form_name,
                                              translate(@form_name,
                                                        '0123456789 ',
                                                        ''),
                                              '')),
                                  ' '),' ')" data-type="number"/>
            <xsl:sort select="substring-after(
                                normalize-space(
                                  translate(@form_name,
                                            translate(@form_name,
                                                      '0123456789 ',
                                                      ''),
                                            '')),
                                  ' ')" data-type="number"/>
        </xsl:apply-templates>
    </xsl:template>
</xsl:stylesheet>

انتاج:

<FORM lob="BO" form_name="AI OM 10"></FORM>
<FORM lob="BO" form_name="AI OM 98"></FORM>
<FORM lob="BO" form_name="AI OM 107"></FORM>
<FORM lob="BO" form_name="CL BP 00 02"></FORM>
<FORM lob="BO" form_name="CL BP 00 02"></FORM>
<FORM lob="BO" form_name="CL BP 03 01"></FORM>
<FORM lob="BO" form_name="123 DDE"></FORM>

XSLT 2.0 الحل: ورقة الأنماط هذه

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="forms">
        <xsl:apply-templates>
            <xsl:sort select="string-join(tokenize(@form_name,' ')
                                            [not(. castable as xs:integer)],
                                          ' ')"/>
            <xsl:sort select="xs:integer(tokenize(@form_name,' ')
                                            [. castable as xs:integer][1])"/>
            <xsl:sort select="xs:integer(tokenize(@form_name,' ')
                                            [. castable as xs:integer][2])"/>
        </xsl:apply-templates>
    </xsl:template>
</xsl:stylesheet>

تجدر الإشارة إلى أن الإجابة المحددة لا تعمل في جميع الحالات.

مدخل:

<forms>
  <FORM lob="BO" form_name="AA 11 AB"/>
  <FORM lob="BO" form_name="AA AZ 01"/>
</forms>

الناتج المتوقع:

<forms>
  <FORM lob="BO" form_name="AA AZ 01"/>
  <FORM lob="BO" form_name="AA 11 AB"/>
</forms>

الناتج الحقيقي:

<forms>
  <FORM lob="BO" form_name="AA 11 AB"/>
  <FORM lob="BO" form_name="AA AZ 01"/>
</forms>

إذا تم السماح رسائل بعد الأرقام ، فلا يمكنك تجريدها في مفتاح الفرز الأول.

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