อะไรคือความแตกต่างระหว่าง 'call-template' และ 'apply-template' ใน XSL?


119

ฉันใหม่ใน XSLT ดังนั้นฉันจึงสับสนเล็กน้อยเกี่ยวกับสองแท็ก

<xsl:apply-templates name="nodes">

และ

<xsl:call-template select="nodes"> 

คุณสามารถระบุความแตกต่างระหว่างพวกเขาได้หรือไม่?

คำตอบ:


167

<xsl:call-template> ใกล้เคียงกับการเรียกใช้ฟังก์ชันในภาษาโปรแกรมแบบดั้งเดิม

คุณสามารถกำหนดฟังก์ชันใน XSLT ได้เช่นเดียวกับฟังก์ชันง่ายๆนี้ที่ส่งออกสตริง

<xsl:template name="dosomething">
  <xsl:text>A function that does something</xsl:text>
</xsl:template>

<xsl:call-template name="dosomething">ฟังก์ชั่นนี้สามารถเรียกผ่าน

<xsl:apply-templates>แตกต่างกันเล็กน้อยและในนั้นคือพลังที่แท้จริงของ XSLT: ใช้โหนด XML จำนวนเท่าใดก็ได้ (สิ่งที่คุณกำหนดในselectแอตทริบิวต์) ทำซ้ำ ( สิ่งนี้สำคัญ: ใช้เทมเพลตทำงานเหมือนวนซ้ำ! ) และค้นหาเทมเพลตที่ตรงกัน สำหรับพวกเขา:

<!-- sample XML snippet -->
<xml>
  <foo /><bar /><baz />
</xml>

<!-- sample XSLT snippet -->
<xsl:template match="xml">
  <xsl:apply-templates select="*" /> <!-- three nodes selected here -->
</xsl:template>

<xsl:template match="foo"> <!-- will be called once -->
  <xsl:text>foo element encountered</xsl:text>
</xsl:template>

<xsl:template match="*"> <!-- will be called twice -->
  <xsl:text>other element countered</xsl:text>
</xsl:template>

วิธีนี้ทำให้คุณเลิกควบคุมโปรเซสเซอร์ XSLT เพียงเล็กน้อย - ไม่ใช่คุณตัดสินใจว่าโฟลว์ของโปรแกรมจะไปที่ใด แต่โปรเซสเซอร์ทำโดยการค้นหาการจับคู่ที่เหมาะสมที่สุดสำหรับโหนดที่กำลังประมวลผลอยู่

หากหลายเทมเพลตสามารถจับคู่กับโหนดได้เทมเพลตที่มีนิพจน์การจับคู่เฉพาะเจาะจงมากขึ้นจะชนะ หากมีเทมเพลตที่ตรงกันมากกว่าหนึ่งรายการที่มีความเฉพาะเจาะจงเดียวกันเทมเพลตที่ประกาศว่าชนะครั้งสุดท้าย

คุณสามารถมีสมาธิในการพัฒนาเทมเพลตได้มากขึ้นและใช้เวลาในการทำ "ประปา" น้อยลง โปรแกรมของคุณจะมีประสิทธิภาพมากขึ้นและเป็นโมดูลาร์ซ้อนกันน้อยลงและเร็วขึ้น (เนื่องจากโปรเซสเซอร์ XSLT ได้รับการปรับให้เหมาะสมสำหรับการจับคู่เทมเพลต)

แนวคิดที่ต้องทำความเข้าใจกับ XSLT คือ "โหนดปัจจุบัน" เมื่อ<xsl:apply-templates>โหนดปัจจุบันย้ายไปพร้อมกับการทำซ้ำทุกครั้งในขณะที่<xsl:call-template>ไม่เปลี่ยนโหนดปัจจุบัน กล่าวคือ.ภายในเทมเพลตที่เรียกว่าหมายถึงโหนดเดียวกันกับ.ในเทมเพลตการโทร นี่ไม่ใช่กรณีที่ใช้เทมเพลต

นี่คือความแตกต่างพื้นฐาน มีลักษณะอื่น ๆ ของเทมเพลตที่ส่งผลต่อพฤติกรรมของพวกเขา: เทมเพลตmodeและpriorityความจริงที่ว่าเทมเพลตสามารถมีได้ทั้ง a nameและmatch. นอกจากนี้ยังมีผลกระทบว่ามีการนำเข้าเทมเพลต ( <xsl:import>) หรือไม่ สิ่งเหล่านี้เป็นการใช้งานขั้นสูงและคุณสามารถจัดการได้เมื่อไปถึงที่นั่น


5
@Tomalak: ตอบดี! อย่างไรก็ตามคำสั่ง: "xsl: apply-template is a loop" ไม่ถูกต้อง ไม่มีข้อบ่งชี้ในข้อกำหนด W3C อย่างเป็นทางการใด ๆ ที่<xsl:apply-templates>ต้องนำมาใช้เป็นลูป - ในทางกลับกันอาจใช้งานควบคู่กันได้เนื่องจากแอปพลิเคชันที่แตกต่างกันบนโหนดต่างๆของรายการโหนดนั้นเป็นอิสระจากกันอย่างแน่นอน
Dimitre Novatchev

8
@ Dimitre: สิ่งที่ฉันตั้งใจจะพูด: จากมุมมองของผู้ใช้ปลายทาง<xsl:apply-templates>ทำตัวเหมือนวนซ้ำ ความแตกต่างของการนำไปใช้งานในส่วนท้ายของโปรเซสเซอร์ XSLT จะไม่ส่งผลกระทบต่อฉันในฐานะโปรแกรมเมอร์ XSLT ผลลัพธ์จะเหมือนกันอย่างแน่นอนสำหรับการใช้งานแบบขนานและแบบวนซ้ำ แต่สำหรับมือใหม่ XSLT ที่มีภูมิหลังที่จำเป็นจะช่วยให้จินตนาการได้<xsl:apply-templates>ว่าเป็นแบบสำหรับแต่ละลูปแม้ว่าในทางเทคนิคจะไม่ใช่ก็ตาม
Tomalak

@ Tomalak: แม้ว่าสิ่งนี้อาจเป็นประโยชน์สำหรับนักเขียนโปรแกรม XSLT มือใหม่ แต่ฉันคิดว่ามันมักจะทำให้พวกเขาเข้าใจผิดเนื่องจากพวกเขาคิดว่าสามารถใช้ข้อมูลสถานะที่สะสมใน "การดำเนินการลูป" ซ้ำได้
Dimitre Novatchev

@Tomalak: เนื่องจากข้อเท็จจริงเหล่านี้ฉันคิดว่าการแก้ไข "xsl: apply-template is a loop" จึงเหมาะสมกับการใช้งานเช่น: "xsl: apply-template is like a loop"
Dimitre Novatchev

@ Tomalak: การวนซ้ำคือการวนซ้ำบางสิ่งapply-templatesและcall-templateคำแนะนำไม่ได้มีไว้สำหรับ เป็นกลไกการเรียกซ้ำใน XSLT และตามที่ Dimitre ตอบแล้วการใช้เทมเพลตคือความหลากหลายหรือกลไกขับเคลื่อนข้อมูล

15

หากต้องการเพิ่มคำตอบที่ดีโดย @Tomalak:

ความแตกต่างที่สำคัญและไม่ได้กล่าวถึงมีดังนี้:

  1. xsl:apply-templatesมากยิ่งขึ้นและลึกกว่าxsl:call-templatesและแม้กระทั่งจาก xsl:for-each,เพียงเพราะเราไม่ทราบว่ารหัสจะนำไปใช้บนโหนดของการเลือก - ในกรณีทั่วไปรหัสนี้จะแตกต่างกันสำหรับโหนดที่แตกต่างกันของโหนดรายการ

  2. รหัสที่จะนำไปใช้สามารถเขียนได้หลังจากxsl:apply templateเขียน sและโดยบุคคลที่ไม่รู้จักผู้เขียนต้นฉบับ

การใช้ไลบรารี FXSLของฟังก์ชันลำดับที่สูงขึ้น (HOF) ใน XSLT จะไม่สามารถทำได้หาก XSLT ไม่มี<xsl:apply-templates>คำสั่ง

สรุป : เทมเพลตและ<xsl:apply-templates>คำแนะนำคือวิธีที่ XSLT ใช้และจัดการกับความหลากหลาย

อ้างอิง : ดูหัวข้อทั้งหมดนี้: http://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200411/msg00546.html


8

xsl:apply-templatesโดยปกติจะใช้ (แต่ไม่จำเป็น) เพื่อประมวลผลชายน์ทั้งหมดหรือส่วนย่อยของโหนดปัจจุบันด้วยเทมเพลตที่เกี่ยวข้องทั้งหมด สิ่งนี้สนับสนุนการเรียกซ้ำของแอ็พพลิเคชัน XSLT ซึ่งตรงกับการเรียกซ้ำ (เป็นไปได้) ของ XML ที่ประมวลผล

xsl:call-templateในทางกลับกันก็เหมือนกับการเรียกใช้ฟังก์ชันทั่วไป คุณเรียกใช้เทมเพลต (ชื่อ) หนึ่งเทมเพลตโดยปกติจะมีพารามิเตอร์อย่างน้อยหนึ่งตัว

ดังนั้นฉันจึงใช้xsl:apply-templatesถ้าฉันต้องการสกัดกั้นการประมวลผลของโหนดที่น่าสนใจและ (โดยปกติ) จะฉีดอะไรบางอย่างลงในสตรีมเอาต์พุต ตัวอย่างทั่วไป (แบบง่าย) จะเป็น

<xsl:template match="foo">
  <bar>
    <xsl:apply-templates/>
  </bar>
</xsl:template>

ในขณะที่xsl:call-templateฉันมักจะแก้ปัญหาเช่นการเพิ่มข้อความของโหนดย่อยบางโหนดเข้าด้วยกันการเปลี่ยนชุดโหนดที่เลือกให้เป็นข้อความหรือชุดโหนดอื่น ๆ และสิ่งที่คล้ายกัน - อะไรก็ตามที่คุณจะเขียนฟังก์ชันพิเศษที่ใช้ซ้ำได้

แก้ไข:

เป็นข้อสังเกตเพิ่มเติมสำหรับข้อความคำถามเฉพาะของคุณ:

<xsl:call-template name="nodes"/> 

สิ่งนี้เรียกเทมเพลตที่มีชื่อว่า 'nodes':

    <xsl:template name="nodes">...</xsl:template>

นี่เป็นความหมายที่แตกต่างจาก:

<xsl:apply-templates select="nodes"/>

... ซึ่งใช้แม่แบบทั้งหมดกับลูกทั้งหมดของโหนด XML ปัจจุบันของคุณที่มีชื่อเป็น 'โหนด'


2

ฟังก์ชันการทำงานนั้นคล้ายคลึงกันมาก (นอกเหนือจากการเรียกความหมายโดยที่call-templateต้องใช้nameแอตทริบิวต์และเทมเพลตชื่อที่เกี่ยวข้อง)

อย่างไรก็ตามโปรแกรมแยกวิเคราะห์จะไม่ดำเนินการในลักษณะเดียวกัน

จากMSDN :

ซึ่งแตกต่าง<xsl:apply-templates>, <xsl:call-template>ไม่เปลี่ยนแปลงโหนดปัจจุบันหรือในปัจจุบันโหนดรายการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.