سؤال

بالنظر إلى ملف XML التالي:

<current>
  <login_name>jd</login_name>
</current>
<people>
  <person>
    <first>John</first>
    <last>Doe</last>
    <login_name>jd</login_name>
  </preson>
  <person>
    <first>Pierre</first>
    <last>Spring</last>
    <login_name>ps</login_name>
  </preson>
</people>

كيف يمكنني الحصول على "John Doe" من داخل المطابق الحالي/تسجيل الدخول؟

حاولت ما يلي:

<xsl:template match="current/login_name">
  <xsl:value-of select="../people/first[login_name = .]"/>
  <xsl:text> </xsl:text>
  <xsl:value-of select="../people/last[login_name = .]"/>
</xsl:template>
هل كانت مفيدة؟

المحلول

سأحدد مفتاحًا لفهرسة الأشخاص:

<xsl:key name="people" match="person" use="login_name" />

يؤدي استخدام المفتاح هنا إلى الحفاظ على نظافة الرمز، ولكن قد تجد أنه من المفيد أيضًا تحقيق الكفاءة إذا كنت تحتاج في كثير من الأحيان إلى استرداد الرمز <person> العناصر على أساسها <login_name> طفل.

سيكون لدي قالب يعرض الاسم المنسق لملف معين <person>:

<xsl:template match="person" mode="name">
  <xsl:value-of select="concat(first, ' ', last)" />
</xsl:template>

وبعد ذلك سأفعل:

<xsl:template match="current/login_name">
  <xsl:apply-templates select="key('people', .)" mode="name" />
</xsl:template>

نصائح أخرى

انت تريد current() وظيفة

<xsl:template match="current/login_name">
  <xsl:value-of select="../../people/person[login_name = current()]/first"/>
  <xsl:text> </xsl:text>
  <xsl:value-of select="../../people/person[login_name = current()]/last"/>
</xsl:template>

أو أكثر نظافة قليلاً:

<xsl:template match="current/login_name">
  <xsl:for-each select="../../people/person[login_name = current()]">
    <xsl:value-of select="first"/>
    <xsl:text> </xsl:text>
    <xsl:value-of select="last"/>
  </xsl:for-each>
</xsl:template>

إذا كنت بحاجة إلى الوصول إلى عدة مستخدمين، إذن جيني تي <xsl:key /> يقترب مثالي.

إليكم البديل الذي أتناوله:

<xsl:template match="current/login_name">
    <xsl:variable name="person" select="//people/person[login_name = .]" />
    <xsl:value-of select="concat($person/first, ' ', $person/last)" />
</xsl:template>

نقوم بتعيين المحدد <person> العقدة إلى متغير، ثم نستخدم concat() وظيفة لإخراج الأسماء الأولى/الأخيرة.

يوجد أيضًا خطأ في مثال XML الخاص بك.ال <person> العقدة تنتهي بشكل غير صحيح ب </preson> (خطأ مطبعي)

يمكن تقديم حل أفضل إذا عرفنا البنية العامة لوثيقة XML (مع العقد الجذرية، وما إلى ذلك)

أعتقد أن ما أراده بالفعل هو الاستبدال في تطابق العقدة "الحالية"، وليس تطابقًا في عقدة الشخص:

<xsl:variable name="login" select="//current/login_name/text()"/>

<xsl:template match="current/login_name">
<xsl:value-of select='concat(../../people/person[login_name=$login]/first," ", ../../people/person[login_name=$login]/last)'/>

</xsl:template>

فقط لإضافة أفكاري إلى المكدس

<xsl:template match="login_name[parent::current]">
 <xsl:variable name="login" select="text()"/>
 <xsl:value-of select='concat(ancestor::people/child::person[login_name=$login]/child::first/text()," ",ancestor::people/child::person[login_name=$login]/child::last/text())'/>
</xsl:template>

أفضل دائمًا استخدام المحاور بشكل صريح في XPath الخاص بي، فهي أكثر تفصيلاً ولكن أكثر وضوحًا IMHO.

اعتمادًا على الشكل الذي تبدو عليه بقية مستندات XML (على افتراض أن هذا مجرد جزء) قد تحتاج إلى تقييد المرجع بـ "ancestor::people" على سبيل المثال استخدام "ancestor::people[1]" لتقييده بالأشخاص الأوائل سلف.

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