2012-04-27 33 views
6

मान लें कि मेरे पास $a, $b, $c और $d हैं जो सभी धारण संख्याएं हैं। मैं सबसे छोटा (सबसे बड़ा) मूल्य प्राप्त करना चाहता हूं। यह करने के लिए मेरे ठेठ XSLT 1.0 दृष्टिकोणचर के समूह से सबसे छोटा मूल्य कैसे चुनें?

<xsl:variable name="minimum"> 
    <xsl:for-each select="$a | $b | $c | $d"> 
    <xsl:sort 
     select="." 
     data-type="number" 
     order="ascending" /> 
    <xsl:if test="position()=1"><xsl:value-of select="." /></xsl:if> 
    </xsl:for-each> 
</xsl:variable> 

है लेकिन, मेरा xslt 1.0 प्रोसेसर

runtime error: file stylesheet.xslt line 106 element for-each
The 'select' expression does not evaluate to a node set.

साथ शिकायत मैं दिए गए मूल्यों के कम से कम (अधिकतम) की गणना कर सकता कैसे?


बेशक, मैं <xsl:when> बयानों की एक लंबी श्रृंखला इस्तेमाल कर सकते हैं और सभी संयोजनों की जांच, लेकिन मैं नहीं बल्कि एक छोटे समाधान चाहते हैं।

+0

मुख्य समस्या यह है, मुझे लगता है, कि संख्या नोड्स नहीं हैं। – cHao

+0

मुझे लगता है कि मुख्य समस्या यह है कि एक्सएसएलटी 1.0 में, 'चयन' में अभिव्यक्ति को नोड-सेट पर मूल्यांकन करना होगा। (http://www.w3.org/TR/xslt#for-each) –

उत्तर

5

चर स्थिर मूल्यों (गतिशील रूप से गणना नहीं) में परिभाषित किया गया है, तो निम्नलिखित की तरह कुछ XSLT 1.0 साथ किया जा सकता:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text"/> 

<xsl:variable name="vA" select="3"/> 
<xsl:variable name="vB" select="1"/> 
<xsl:variable name="vC" select="9"/> 
<xsl:variable name="vD" select="5"/> 

<xsl:template match="/"> 
    <xsl:for-each select= 
     "document('')/*/xsl:variable 
     [contains('|vA|vB|vC|vD|', concat('|', @name, '|'))] 
      /@select 
     "> 
     <xsl:sort data-type="number" order="ascending"/> 

     <xsl:if test="position() = 1"> 
     Smallest: <xsl:value-of select="."/> 
     </xsl:if> 
     <xsl:if test="position() = last()"> 
     Largest: <xsl:value-of select="."/> 
     </xsl:if> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

जब इस बदलाव किसी भी XML दस्तावेज़ (नहीं पर लागू किया जाता है प्रयुक्त), चाहता था, सही परिणाम उत्पादन किया जाता है:

Smallest: 1 
    Largest: 9 

द्वितीय। अब, मान लें कि चर गतिशील रूप से परिभाषित किए गए हैं।

हम इस की तरह कुछ कर सकते हैं (लेकिन xxx:node-set() विस्तार समारोह की जरूरत है):

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ext="http://exslt.org/common"> 
<xsl:output method="text"/> 

<xsl:variable name="vA" select="number(/*/*[3])"/> 
<xsl:variable name="vB" select="number(/*/*[1])"/> 
<xsl:variable name="vC" select="number(/*/*[9])"/> 
<xsl:variable name="vD" select="number(/*/*[5])"/> 

<xsl:template match="/"> 
    <xsl:variable name="vrtfStore"> 
     <num><xsl:value-of select="$vA"/></num> 
     <num><xsl:value-of select="$vB"/></num> 
     <num><xsl:value-of select="$vC"/></num> 
     <num><xsl:value-of select="$vD"/></num> 
    </xsl:variable> 

    <xsl:for-each select="ext:node-set($vrtfStore)/*"> 
     <xsl:sort data-type="number" order="ascending"/> 

     <xsl:if test="position() = 1"> 
     Smallest: <xsl:value-of select="."/> 
     </xsl:if> 
     <xsl:if test="position() = last()"> 
     Largest: <xsl:value-of select="."/> 
     </xsl:if> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

जब इस बदलाव निम्नलिखित XML दस्तावेज़ पर भी लागू होता है:

<nums> 
    <num>01</num> 
    <num>02</num> 
    <num>03</num> 
    <num>04</num> 
    <num>05</num> 
    <num>06</num> 
    <num>07</num> 
    <num>08</num> 
    <num>09</num> 
    <num>10</num> 
</nums> 

चाहता था, सही परिणाम उत्पन्न होता है:

Smallest: 1 
    Largest: 9 
+0

तो दस्तावेज़ ('') एक्सएसएलटी एक्सएमएल को इंगित करता है? क्या इसे फिर से पर्स करना होगा? हालांकि, एक और फैंसी चाल मैं सीखता हूं, धन्यवाद। +1 –

+0

@PavelVeller: हां, यह अक्सर उपयोग किया जाता है यदि आप XSLT स्टाइलशीट में इनलाइन डेटा रखना चाहते हैं और एक अलग फ़ाइल में नहीं। हां, पुन: पार्स निष्पादन समय पर किया जाता है और यह बहुत प्रभावी नहीं है। आप भी समाधान के दूसरे भाग को देखने में रुचि रखते हैं। –

+0

दूसरा भाग चाल है, धन्यवाद। मेरे चर इनपुट इनपुट पेड़ पर अधिक जटिल अभिव्यक्तियों के न्यूनतम हैं, इसलिए निश्चित रूप से स्थैतिक नहीं है। – bitmask

1

मैं 1.0 (मैं 2.0 का उपयोग) में यह करने के लिए किया था कभी नहीं किया है, लेकिन आप ऐसा कर सकता है:

<xsl:variable name="minimum"> 
    <xsl:choose> 
     <xsl:when test="$b > $a and $c > $a and $d > $a"><xsl:value-of select="$a"/></xsl:when> 
     <xsl:when test="$a > $b and $c > $b and $d > $b"><xsl:value-of select="$b"/></xsl:when> 
     <xsl:when test="$b > $c and $a > $c and $d > $c"><xsl:value-of select="$c"/></xsl:when> 
     <xsl:when test="$b > $d and $c > $d and $a > $d"><xsl:value-of select="$d"/></xsl:when> 
    </xsl:choose> 
    </xsl:variable> 

वहाँ एक बेहतर तरीका है, हालांकि हो गया है।

+0

मेरी सोच बिल्कुल ठीक है। जैसा कि मैंने कहा, मेरे पास पहले से ही एक आकस्मिक योजना के रूप में है।लेकिन यह अच्छा नहीं है, और यह निश्चित रूप से पैमाने पर नहीं है। – bitmask

+0

@bitmask - मैंने पूरी तरह से आपके प्रश्न के अंतिम पैराग्राफ को याद किया जहां आपने कहा था कि आप ऐसा कर सकते हैं। उम्मीद है कि किसी (@DimitreNovatchev शायद) का एक बेहतर समाधान होगा। –

3

यह एक्सएसएलटी 1.0 समाधान सूची से न्यूनतम/अधिकतम मूल्य वापस करने के लिए मानों की एक सीमित सूची को पार्स करने के लिए रिकर्सिव टेम्पलेट का उपयोग करता है।

<?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" version="1.0" encoding="UTF-8" indent="yes"/> 

    <xsl:variable name="a" select="'3'"/> 
    <xsl:variable name="b" select="'1'"/> 
    <xsl:variable name="c" select="'9'"/> 
    <xsl:variable name="d" select="'5'"/> 

    <xsl:template match="/"> 
     <xsl:text>&#xa;Smallest: </xsl:text> 
     <xsl:call-template name="min"> 
      <xsl:with-param name="values" select="concat($a,',',$b,',',$c,',',$d)"/>  
     </xsl:call-template> 

     <xsl:text>&#xa;Largest: </xsl:text> 
     <xsl:call-template name="max"> 
      <xsl:with-param name="values" select="concat($a,',',$b,',',$c,',',$d)"/>  
     </xsl:call-template> 
    </xsl:template> 

    <xsl:template name="min"> 
     <xsl:param name="values" /> 
     <xsl:param name="delimiter" select="','"/> 
     <xsl:param name="min"/> 

     <xsl:variable name="currentValue" > 
      <xsl:choose> 
       <xsl:when test="contains($values, $delimiter)"> 
        <xsl:value-of select="substring-before($values,$delimiter)"/> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:value-of select="$values"/> 
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:variable> 

     <xsl:variable name="minimumValue"> 
      <xsl:choose> 
       <xsl:when test="$min and $min > $currentValue"> 
        <xsl:value-of select="$currentValue"/> 
       </xsl:when> 
       <xsl:when test="$min"> 
        <xsl:value-of select="$min"/> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:value-of select="$currentValue" /> 
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:variable> 

     <xsl:choose> 
      <xsl:when test="substring-after($values,$delimiter)"> 
       <xsl:call-template name="min"> 
        <xsl:with-param name="min" select="$minimumValue" /> 
        <xsl:with-param name="values" select="substring-after($values,$delimiter)" /> 
        <xsl:with-param name="delimiter" select="$delimiter"/> 
       </xsl:call-template> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="$minimumValue" /> 
      </xsl:otherwise> 
     </xsl:choose>     
    </xsl:template> 


    <xsl:template name="max"> 
     <xsl:param name="values" /> 
     <xsl:param name="delimiter" select="','"/> 
     <xsl:param name="max"/> 

     <xsl:variable name="currentValue" > 
      <xsl:choose> 
       <xsl:when test="contains($values, $delimiter)"> 
        <xsl:value-of select="substring-before($values,$delimiter)"/> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:value-of select="$values"/> 
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:variable> 

     <xsl:variable name="maximumValue"> 
      <xsl:choose> 
       <xsl:when test="$max and $currentValue > $max"> 
        <xsl:value-of select="$currentValue"/> 
       </xsl:when> 
       <xsl:when test="$max"> 
        <xsl:value-of select="$max"/> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:value-of select="$currentValue" /> 
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:variable> 

     <xsl:choose> 
      <xsl:when test="substring-after($values,$delimiter)"> 
       <xsl:call-template name="max"> 
        <xsl:with-param name="max" select="$maximumValue" /> 
        <xsl:with-param name="values" select="substring-after($values,$delimiter)" /> 
        <xsl:with-param name="delimiter" select="$delimiter"/> 
       </xsl:call-template> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="$maximumValue" /> 
      </xsl:otherwise> 
     </xsl:choose>     
    </xsl:template> 
</xsl:stylesheet> 

जब मार डाला है, तो निम्न उत्पादन का उत्पादन:

Smallest: 1 
Largest: 9