xslt
2010-10-07 12 views 9 likes 
9

मैं XSL के लिए एक यथोचित जटिल फोन है: लागू-टेम्पलेट्स:एक्सएसएल चर का उपयोग xsl में कैसे करें: लागू-टेम्पलेट्स?

<xsl:apply-templates select="columnval[@id 
             and not(@id='_Name_') 
             and not(@id='Group') 
             and not(@id='_Count_')]"/> 

अभिव्यक्ति इस तरह अन्य स्थानों में पुन: उपयोग किया जाता है:

<xsl:apply-templates select="someothernode[@id 
              and not(@id='_Name_') 
              and not(@id='Group') 
              and not(@id='_Count_')]"/> 

मैं इसे किसी भी तरह सामान्यीकरण करने के लिए चाहते हैं, तो मैं परिभाषित कर सकते हैं यह एक बार और इसे कहीं और पुन: उपयोग करें। हालांकि, यह काम नहीं कर रहा है:

<xsl:variable name="x">@id and not(@id='_Name_') and not(@id='Group') and not(@id='_Count_')</xsl:variable> 
<xsl:apply-templates select="columnval[$x]"/> 
<xsl:apply-templates select="someothernode[$x]"/> 

क्या ऐसा करने का एक बेहतर/अलग तरीका है? मैं चाहता हूं कि एक्सएसएल में एकाधिक अलग-अलग कॉलों में xpath अभिव्यक्ति का पुन: उपयोग करना है: लागू-टेम्पलेट्स (जिनमें से कुछ अलग-अलग बच्चों से चयन करते हैं)।

यह क्लाइंट एप्लिकेशन में उपयोग किया जा रहा है, इसलिए मैं किसी भी एक्सटेंशन का उपयोग नहीं कर सकता या दुर्भाग्यवश XSLT 2 पर स्विच नहीं कर सकता। :(

धन्यवाद।

+0

अच्छा प्रश्न है। दो संभावित समाधानों (एक्सएसएलटी 1.0 और एक्सएसएलटी 2.0) के वर्णन के लिए मेरा उत्तर देखें और उच्च-आदेश कार्यों का उपयोग करके अधिक शक्तिशाली, समाधान का संकेत दें। –

उत्तर

5

आप XSLT में गतिशील रूप से XPath का निर्माण नहीं कर सकते (कम से कम, XSLT 1.0 नहीं)। लेकिन आप आसानी से पूरा कर सकते हैं आप टेम्पलेट साधनों का उपयोग करने के लिए कोशिश कर रहे हैं क्या:

<xsl:apply-templates select="columnval" mode="filter"/> 
<xsl:apply-template select="someothernode" mode="filter"/> 

... 

<!-- this guarantees that elements that don't match the filter don't get output --> 
<xsl:template match="*" mode="filter"/> 

<xsl:template match="*[@id and not(@id='_Name_') and not(@id='Group') and not(@id='_Count_')]" mode="filter"> 
    <xsl:apply-templates select="." mode="filtered"/> 
</xsl:template> 

<xsl:template match="columnval" mode="filtered"> 
    <!-- this will only be applied to the columnval elements that pass the filter --> 
</xsl:template> 

<xsl:template match="someothernode" mode="filtered"> 
    <!-- this will only be applied to the someothernode elements that pass the filter --> 
</xsl:template> 
+0

+1 यह एक कुशल दृष्टिकोण है। केवल नकारात्मक पक्ष यह है कि फिल्टर हार्डकोड किया गया है और इसलिए परिवर्तनीय नहीं है। यदि एक परिवर्तनीय फ़िल्टर की आवश्यकता नहीं है, तो मैं इस समाधान के साथ जाऊंगा। – Tomalak

+0

टेम्पलेट मोड ने मुझे कोई समझ नहीं दी जब तक मैंने ओपी की समस्याओं में भागना शुरू नहीं किया। –

1

मैं एक एक्सटेंशन का उपयोग XSLT करने पर एक नज़र ले जाएगा। मुझे नहीं लगता कि आप "मानक" xslt में कर सकते हैं।

इस विस्तार आप क्या चाहते हैं कर सकते हैं : http://www.exslt.org/dyn/functions/evaluate/index.html

+0

अपडेट किया गया प्रश्न - हम एक्सटेंशन का उपयोग नहीं कर सकते हैं, क्योंकि हम ट्रांसफॉर्म करने के लिए एमएसएक्सएमएल पर भरोसा कर रहे हैं :( – Colen

+0

'msxsl: node-set' काम करेगा, फिर –

1
विस्तार exsl साथ

:। nodeset, आप एक नामित टेम्पलेट है कि एक nodeset $ x स्वीकार करता है और देता है अपने स्थिर विधेय के अनुसार nodeset फ़िल्टर्ड

तुम भी एक समारोह को परिभाषित कर सकते, XSLT 2.0 में बना सकते हैं

+0

अपडेट किया गया प्रश्न - दुर्भाग्य से हम एक्सएसएलटी 1.0 के साथ फंस गए हैं। ( – Colen

1

कैसे के बारे में:

<xsl:variable name="filter" select="_Name_|Group|_Count_" /> 

<xsl:apply-templates select="columnval" mode="filtered" /> 
<xsl:apply-templates select="someothernode" mode="filtered" /> 

<xsl:template match="someothernode|columnval" mode="filtered"> 
    <xsl:if test="not(contains(
    concat('|', $filter,'|'), 
    concat('|', @id,'|'), 
))"> 
    <!-- whatever --> 
    </xsl:if> 
</xsl:template> 

आप $filter एक परम कर सकता है, और यह उदाहरण के लिए बाहर से गुजरती हैं।

आप क्या नहीं कर सकते (जैसा कि आपने देखा है) XPath अभिव्यक्तियों को संग्रहीत करने के लिए चर का उपयोग किया जाता है।

+0

बेवकूफ सवाल - आप पैरामीटर के साथ ऐसा क्यों कर सकते हैं, लेकिन चर नहीं? – Colen

+0

@Colen: परिवर्तनीय (या उस मामले के लिए पैरामीटर) '$ फ़िल्टर' एक स्ट्रिंग को स्टोर करता है, अभिव्यक्ति नहीं। मैंने' | 'को चुना है delimiter .-) – Tomalak

1

दोनों XSLT 1.0 और XSLT 2.0 गतिशील मूल्यांकन का समर्थन नहीं करते।

एक तरह से यह करने के लिए XSLT 1.0 में XSLT 2.0 में <xsl:function> या <xsl:call-template> उपयोग कर रहा है।

<xsl:function name="my:test" as="xs:boolean"> 
    <xsl:param name="pNode" as="element()"/> 

    <xsl:variable name="vid" select="$pNode/@id"/> 

    <xsl:sequence select= 
    "$vid and not($vid=('_Name_','Group','_Count_')"/> 
</xsl:function> 

तो आप इस समारोह इस्तेमाल कर सकते हैं:

<xsl:apply-templates select="columnval[my:test(.)]"/> 

निश्चित रूप से, आप के रूप में रॉबर्ट Rossney ने सुझाव दिया विशिष्ट मैच पैटर्न में परीक्षण निर्दिष्ट कर सकते हैं, और इस का सबसे अच्छा तरीका हो सकता है।

मामले में आप करने की जरूरत है गतिशील जो छानने समारोह का उपयोग करने के परिभाषित करते हैं, एक शक्तिशाली उपकरण FXSL पुस्तकालय, जो XSLT में उच्च क्रम-कार्य (HOF) को लागू करता है। एचओएफ ऐसे कार्य होते हैं जो पैरामीटर के रूप में अन्य कार्यों को स्वीकार करते हैं और एक परिणाम को उनके परिणाम के रूप में वापस कर सकते हैं।

इस दृष्टिकोण का उपयोग करके, आप डायनामिक रूप से my:test() को पैरामीटर के रूप में परीक्षण करने वाले फ़ंक्शन के रूप में निर्धारित करते हैं और पास करते हैं।

2

पुनर्रचना @Robert Rossney और @Tomalak

<xsl:apply-templates select="columnval" mode="filter"/> 
<xsl:apply-templates select="someothernode" mode="filter"/> 

<xsl:template match="*" mode="filter"> 
    <xsl:param name="pFilter" select="'_Name_|Group|_Count_'"/> 
    <xsl:apply-templates select="self::* 
           [not(contains( 
             concat('|',$pFilter,'|'), 
             concat('|',@id,'|'))) 
           and @id]"/> 
</xsl:template> 
+1

गुण गुणों के परिभाषा सदस्यों द्वारा हैं, इसलिए आप सामान्य 'नोड() 'को प्रतिस्थापित कर सकते हैं '*'। :-) – Tomalak

संबंधित मुद्दे