تحقق مما إذا كانت السلسلة فارغة أو فارغة في XSLT

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

  •  05-07-2019
  •  | 
  •  

سؤال

كيف يمكنني التحقق مما إذا كانت القيمة فارغة أو فارغة باستخدام XSL?

على سبيل المثال، إذا categoryName فارغ؟أنا أستخدم أ عند الاختيار بناء.

على سبيل المثال:

<xsl:choose>
    <xsl:when test="categoryName !=null">
        <xsl:value-of select="categoryName " />
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="other" />
    </xsl:otherwise>
</xsl:choose>
هل كانت مفيدة؟

المحلول

test="categoryName != ''"

تعديل : في هذا يغطي التفسير الأكثر احتمالا، في رأيي، من "[لا] خالية أو فارغة" كما يستدل من هذه المسألة، بما في ذلك انها الزائفة رمز وبلدي التجربة المبكرة مع XSLT . أي، "ما هو ما يعادل جافا التالية؟":

!(categoryName == null || categoryName.equals(""))

لمزيد من التفاصيل، مثلا، تحديد واضح لاغية مقابل فارغة، انظر الجواب johnvey في ما يلي و / أو <وأ href = "http://xsltransform.net/94hvTAf/3" يختلط = "noreferrer"> وXSLT 'كمان' لقد مقتبس من هذا الجواب، والذي يتضمن الخيار في تعليق مايكل كاي وكذلك السادس ممكن التفسير.

نصائح أخرى

وغياب أي معلومات أخرى، سوف تتولى XML التالية:

<group>
    <item>
        <id>item 1</id>
        <CategoryName>blue</CategoryName>
    </item>
    <item>
        <id>item 2</id>
        <CategoryName></CategoryName>
    </item>
    <item>
        <id>item 3</id>
    </item>
    ...
</group>

وثمة حالة استخدام عينة تبدو:

<xsl:for-each select="/group/item">
    <xsl:if test="CategoryName">
        <!-- will be instantiated for item #1 and item #2 -->
    </xsl:if>
    <xsl:if test="not(CategoryName)">
        <!-- will be instantiated for item #3 -->
    </xsl:if>
    <xsl:if test="CategoryName != ''">
        <!-- will be instantiated for item #1 -->
    </xsl:if>
    <xsl:if test="CategoryName = ''">
        <!-- will be instantiated for item #2 -->
    </xsl:if>
</xsl:for-each>

من عنصر فارغ:

لاختبار ما إذا كانت قيمة عقدة معينة فارغة

ذلك يعتمد على ما تقصده بالفارغ.

  • لا يحتوي على العقد الفرعية: not(node())
  • لا يحتوي على محتوى نصي: not(string(.))
  • لا يحتوي على نص غير المسافة البيضاء: not(normalize-space(.))
  • لا يحتوي على أي شيء باستثناء التعليقات: not(node()[not(self::comment())])

وماذا عن؟

test="not(normalize-space(categoryName)='')"

الاولين صفقة بقيمة اغية والثاني اثنين صفقة مع سلسلة فارغة.

<xsl:if test="USER/FIRSTNAME">
    USERNAME is not null
</xsl:if>
<xsl:if test="not(USER/FIRSTNAME)">
    USERNAME is null
 </xsl:if>
 <xsl:if test="USER/FIRSTNAME=''">
     USERNAME is empty string
 </xsl:if>
 <xsl:if test="USER/FIRSTNAME!=''">
     USERNAME is not empty string
 </xsl:if>

في بعض الحالات، قد كنت تريد أن تعرف عندما تكون القيمة فارغة على وجه التحديد، وهو أمر ضروري خاصة عند استخدام XML التي تم تسلسل من الأشياء. NET. في حين أن الإجابة مقبولة تعمل لهذا، فإنه يعود أيضا إلى نفس النتيجة عندما سلسلة فارغة أو فارغة، أي ''، لذلك لا يمكن أن تفرق.

<group>
    <item>
        <id>item 1</id>
        <CategoryName xsi:nil="true" />
    </item>
</group>

وهكذا يمكنك ببساطة اختبار السمة.

<xsl:if test="CategoryName/@xsi:nil='true'">
   Hello World.
</xsl:if>

وأحيانا يكون من الضروري أن تعرف بالضبط حالة ولا يمكنك ببساطة معرفة ما اذا كان يتم إنشاء مثيل اسم الفئة، لأنه على عكس القول جافا سكريبت

<xsl:if test="CategoryName">
   Hello World.
</xsl:if>

وسيعود ينطبق على عنصر فارغة.

إذا كان هناك احتمال أن العنصر غير موجود في XML أود أن اختبار كل هذا العنصر موجود وأن طول سلسلة أكبر من الصفر:

<xsl:choose>
    <xsl:when test="categoryName and string-length(categoryName) &gt; 0">
        <xsl:value-of select="categoryName " />
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="other" />
    </xsl:otherwise>
</xsl:choose>

أعلم أن هذا السؤال قديم، ولكن بين جميع الإجابات، أفتقد إجابة واحدة تمثل أسلوبًا شائعًا لحالة الاستخدام هذه في تطوير XSLT.

أتخيل أن الكود المفقود من OP يبدو كالتالي:

<xsl:template match="category">
    <xsl:choose>
        <xsl:when test="categoryName !=null">
            <xsl:value-of select="categoryName " />
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="other" />
        </xsl:otherwise>
    </xsl:choose>
</category>

وأن الإدخال يبدو كالتالي:

<categories>
    <category>
       <categoryName>Books</categoryName>
    </category>
    <category>
       <categoryName>Magazines</categoryName>
       <categoryName>Periodicals</categoryName>
       <categoryName>Journals</categoryName>
    </category>
    <category>
        <categoryName><!-- please fill in category --></categoryName>
    </category>
    <category>
        <categoryName />
    </category>
    <category />
</categories>

أي أنني أفترض أنه يمكن أن يكون هناك صفر أو فارغ أو مفرد أو متعدد categoryName عناصر.للتعامل مع كل هذه الحالات باستخدام xsl:chooseأصبحت بنيات النمط، أو بعبارة أخرى، حتمًا، فوضوية بسرعة (وأكثر من ذلك إذا كانت العناصر على مستويات مختلفة!).لغة البرمجة النموذجية في XSLT تستخدم القوالب (وبالتالي T في XSLT)، وهي برمجة تعريفية، وليست ضرورية (أنت لا تخبر المعالج بما يجب أن يفعله، أنت فقط تخبر ما تريد إخراجه إذا تم استيفاء شروط معينة).بالنسبة لحالة الاستخدام هذه، يمكن أن يبدو الأمر كما يلي:

<!-- positive test, any category with a valid categoryName -->
<xsl:template match="category[categoryName[text()]]">
    <xsl:apply-templates />
</xsl:template>

<!-- any other category (without categoryName, "null", with comments etc) -->
<xsl:template match="category">
    <xsl:text>Category: Other</xsl:text>
</xsl:template>

<!-- matching the categoryName itself for easy handling of multiple names -->
<xsl:template match="categoryName">
    <xsl:text>Category: </xsl:text>
    <xsl:value-of select="." />
</xsl:template>

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

لاحظ أنه في هذا السيناريو ليست هناك حاجة للمطابقة بشكل خاص categories أو category, ، لأن المعالج سيقوم تلقائيًا بمعالجة جميع الأطفال، ما لم نخبره بخلاف ذلك (في هذا المثال، لا يقوم القالب الثاني والثالث بمعالجة الأطفال بشكل أكبر، لأنه لا يوجد xsl:apply-templates فيهم).

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

ملحوظة:ليس هناك شيء مثل null في XML.هنالك الحادي عشر: لا شيء, ، ولكن نادرًا ما يتم استخدام ذلك، خاصة نادرًا في السيناريوهات غير المكتوبة دون مخطط من نوع ما.

كيف يمكنني التحقق مما إذا كانت القيمة فارغة أو فارغة باستخدام XSL؟

على سبيل المثال، إذا categoryName فارغ؟

ربما يكون هذا هو أبسط تعبير XPath (الإجابة المقبولة توفر اختبارًا للعكس، وستكون أطول إذا تم نفيها):

not(string(categoryName))

توضيح:

الحجة إلى not() الوظيفة أعلاه هي false() بالضبط عندما لا يكون هناك categoryName الطفل ("فارغ") لعنصر السياق، أو (منفرد) categoryName الطفل لديه قيمة سلسلة - السلسلة الفارغة.

أنا أستخدم أ عند الاختيار بناء.

على سبيل المثال:

<xsl:choose>
    <xsl:when test="categoryName !=null">
        <xsl:value-of select="categoryName " />
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="other" />
    </xsl:otherwise>
</xsl:choose>

في استخدام XSLT 2.0:

<xsl:copy-of select="concat(categoryName,  $vOther[not(string(current()/categoryName))])"/>

هنا مثال كامل:

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

 <xsl:variable name="vOther" select="'Other'"/>

 <xsl:template match="/">
  <xsl:copy-of select="concat(categoryName,$vOther[not(string(current()/categoryName))])"/>
 </xsl:template>
</xsl:stylesheet>

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

<categoryName>X</categoryName>

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

X

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

<categoryName></categoryName>

أو على هذا:

<categoryName/>

أو على هذا

<somethingElse>Y</somethingElse>

يتم إنتاج النتيجة الصحيحة:

Other

وبالمثل، استخدم هذا XSLT 1.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="vOther" select="'Other'"/>

  <xsl:template match="/">
    <xsl:copy-of select=
    "concat(categoryName,  substring($vOther, 1 div not(string(categoryName))))"/>
  </xsl:template>
</xsl:stylesheet>

القيام مذكرة:لا يتم استخدام أي شرطية على الإطلاق.تعرف على المزيد حول أهمية تجنب البنيات الشرطية في دورة Pluralsight الرائعة هذه:

"أنماط التصميم التكتيكي في .NET:التحكم في التدفق"

إذا عقدة ليس لها قيمة المتاحة في أكس المدخلات مثل أدناه كسباث،

<node>
    <ErrorCode/>
</node>

وظيفة سلسلة () تحويل إلى قيمة فارغة. ولذلك فإن هذا يعمل بشكل جيد:

string(/Node/ErrorCode) =''

وشيء من هذا القبيل يعمل بالنسبة لي:

<xsl:choose>
  <xsl:when test="string(number(categoryName)) = 'NaN'"> - </xsl:when> 
  <xsl:otherwise> 
    <xsl:number value="categoryName" />
  </xsl:otherwise>
</xsl:choose>

وأو على العكس من ذلك:

<xsl:choose>
  <xsl:when test="string(number(categoryName)) != 'NaN'">
    <xsl:number value="categoryName" />
  </xsl:when> 
  <xsl:otherwise> - </xsl:otherwise>
</xsl:choose>

ملحوظة: إذا كنت لا تحقق القيم الخالية أو التعامل مع القيم الخالية، IE7 بإرجاع -2147483648 بدلا من نان

ولقد وجدت في الواقع أنه من الأفضل مجرد اختبار لطول سلسلة منذ عدة مرات هذا المجال هو غير فارغة، فقط فارغة

<اقتباس فقرة>   

حسب تجربتي فإن أفضل طريقة هي:

<xsl:when test="not(string(categoryName))">
    <xsl:value-of select="other" />
</xsl:when>
<otherwise>
    <xsl:value-of select="categoryName" />
</otherwise>

استخدم بسيط اسم الفئة / النص () هذا الاختبار يعمل بشكل جيد على <categoryName/> وأيضا <categoryName></categoryName>.

<xsl:choose>
    <xsl:when test="categoryName/text()">
        <xsl:value-of select="categoryName" />
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="other" />
    </xsl:otherwise>
</xsl:choose>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top