XSLT:كيفية عكس الإخراج دون الفرز حسب المحتوى

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

  •  20-09-2019
  •  | 
  •  

سؤال

لدي قائمة بالعناصر:

<item>a</item>
<item>x</item>
<item>c</item>
<item>z</item>

وأريد كما الإخراج

z
c
x
a

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

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

المحلول

رمز XML:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<device>
<element>a</element>
<element>x</element>
<element>c</element>
<element>z</element>
</device>

رمز XSLT:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="//device">
<xsl:for-each select="element">

<xsl:sort select="position()" data-type="number" order="descending"/>

<xsl:text> </xsl:text>
<xsl:value-of select="."/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>

ملحوظة: إذا كنت تستخدم data-type="number"، ولم تكن أي من القيم أرقامًا، فسيتم فرز هذه القيم غير الرقمية قبل القيم الرقمية.وهذا يعني أنك إذا كنت تستخدم order="ascending"، فستظهر القيم غير الرقمية أولاً؛إذا كنت تستخدم الأمر = "تنازلي"، فستظهر القيم غير الرقمية أخيرًا.

يلاحظ أنه لم يتم فرز القيم غير الرقمية؛فهي تظهر ببساطة في مستند الإخراج بالترتيب الذي تمت مواجهتها به.

أيضًا، قد تجد من المفيد قراءة هذا:

http://docstore.mik.ua/orelly/xml/xslt/ch06_01.htm

نصائح أخرى

سأقدم حلين XSLT:

أنا.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:template match="/*">
     <xsl:call-template name="reverse">
       <xsl:with-param name="pList" select="*"/>
     </xsl:call-template>
    </xsl:template>

    <xsl:template name="reverse">
      <xsl:param name="pList"/>

      <xsl:if test="$pList">
        <xsl:value-of
         select="concat($pList[last()], '&#xA;')"/>

        <xsl:call-template name="reverse">
          <xsl:with-param name="pList"
            select="$pList[not(position() = last())]"/>
        </xsl:call-template>
      </xsl:if>
    </xsl:template>
</xsl:stylesheet>

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

<t>
    <item>a</item>
    <item>x</item>
    <item>c</item>
    <item>z</item>
</t>

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

z
c
x
a

ثانيا.حل 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="text"/>

  <xsl:template match="/*">
   <xsl:value-of select="reverse(*)/string(.)"
    separator="&#xA;"/>
  </xsl:template>
</xsl:stylesheet>

عندما يتم تطبيق هذا التحويل على نفس مستند XML, يتم إنتاج نفس النتيجة الصحيحة.

ولست متأكدا ما مثل النظرات XML كاملة، لذلك أنا ملفوفة في عنصر <doc> لجعله بشكل جيد:

<doc>
<item>a</item>
<item>x</item>
<item>c</item>
<item>z</item>
</doc>

وتشغيل هذا المثال XML ضد هذه الأنماط:

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

    <xsl:template match="/">
        <xsl:call-template name="reverse">
            <xsl:with-param name="item" select="doc/item[position()=last()]" />
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="reverse">
        <xsl:param name="item" />

        <xsl:value-of select="$item" />
        <!--Adds a line feed-->
        <xsl:text>&#10;</xsl:text>

        <!--Move on to the next item, if we aren't at the first-->
        <xsl:if test="$item/preceding-sibling::item">
            <xsl:call-template name="reverse">
                <xsl:with-param name="item" select="$item/preceding-sibling::item[1]" />
            </xsl:call-template>
        </xsl:if>

    </xsl:template>

</xsl:stylesheet>

وتنتج الانتاج المطلوبة:

z
c
x
a

وأنت قد تحتاج إلى ضبط XPath لمباراة XML الفعلي.

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

والنظر في هذه المدخلات XML:

<?xml version="1.0" encoding="utf-8" ?>
<items>
  <item>a</item>
  <item>x</item>
  <item>c</item>
  <item>z</item>
</items>

ووXSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="text" />

    <xsl:template match="/items[1]">

      <xsl:variable name="items-list" select="." />
      <xsl:variable name="items-count" select="count($items-list/*)" />

      <xsl:for-each select="item">
        <xsl:variable name="index" select="$items-count+1  - position()"/>
        <xsl:value-of select="$items-list/item[$index]"/>
        <xsl:value-of select="'&#x0a;'"/>
      </xsl:for-each>

    </xsl:template>
</xsl:stylesheet>

والنتيجة:

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